From b7c1eae41fc7008eeae765f143144e0352254078 Mon Sep 17 00:00:00 2001 From: Bob Supnik Date: Fri, 9 Sep 2005 18:09:00 -0700 Subject: [PATCH] Notes For V3.5-0 The source set has been extensively overhauled. For correct viewing, set Visual C++ or Emacs to have tab stops every 4 characters. 1. New Features in 3.4-1 1.1 All Ethernet devices - Added Windows user-defined adapter names (from Timothe Litt) 1.2 Interdata, SDS, HP, PDP-8, PDP-18b terminal multiplexors - Added support for SET n DISCONNECT 1.3 VAX - Added latent QDSS support - Revised autoconfigure to handle QDSS 1.4 PDP-11 - Revised autoconfigure to handle more casees 2. Bugs Fixed in 3.4-1 2.1 SCP and libraries - Trim trailing spaces on all input (for example, attach file names) - Fixed sim_sock spurious SIGPIPE error in Unix/Linux - Fixed sim_tape misallocation of TPC map array for 64b simulators 2.2 1401 - Fixed bug, CPU reset was clearing SSB through SSG 2.3 PDP-11 - Fixed bug in VH vector display routine - Fixed XU runt packet processing (found by Tim Chapman) 2.4 Interdata - Fixed bug in SHOW PAS CONN/STATS - Fixed potential integer overflow exception in divide 2.5 SDS - Fixed bug in SHOW MUX CONN/STATS 2.6 HP - Fixed bug in SHOW MUX CONN/STATS 2.7 PDP-8 - Fixed bug in SHOW TTIX CONN/STATS - Fixed bug in SET/SHOW TTOXn LOG 2.8 PDP-18b - Fixed bug in SHOW TTIX CONN/STATS - Fixed bug in SET/SHOW TTOXn LOG 2.9 Nova, Eclipse - Fixed potential integer overflow exception in divide --- 0readme_34.txt | 38 - 0readme_35.txt | 70 + 0readme_ethernet.txt | 2 +- ALTAIR/altair_cpu.c | 1104 ++-- ALTAIR/altair_defs.h | 20 +- ALTAIR/altair_dsk.c | 198 +- ALTAIR/altair_sio.c | 194 +- ALTAIR/altair_sys.c | 281 +- AltairZ80/altairZ80_cpu.c | 11080 ++++++++++++++++++----------------- AltairZ80/altairZ80_defs.h | 128 +- AltairZ80/altairZ80_dsk.c | 873 +-- AltairZ80/altairZ80_sio.c | 1866 +++--- AltairZ80/altairZ80_sys.c | 1262 ++-- AltairZ80/altairz80_hdsk.c | 616 +- GRI/gri_cpu.c | 892 +-- GRI/gri_defs.h | 242 +- GRI/gri_doc.txt | 4 +- GRI/gri_stddev.c | 346 +- GRI/gri_sys.c | 766 +-- H316/h316_cpu.c | 1725 +++--- H316/h316_defs.h | 252 +- H316/h316_doc.txt | 4 +- H316/h316_dp.c | 1274 ++-- H316/h316_fhd.c | 520 +- H316/h316_lp.c | 423 +- H316/h316_mt.c | 761 +-- H316/h316_stddev.c | 1006 ++-- H316/h316_sys.c | 386 +- HP2100/hp2100_cpu.c | 2221 +++---- HP2100/hp2100_cpu.h | 84 +- HP2100/hp2100_cpu1.c | 2564 ++++---- HP2100/hp2100_defs.h | 400 +- HP2100/hp2100_doc.txt | 5 +- HP2100/hp2100_dp.c | 1310 +++-- HP2100/hp2100_dq.c | 1157 ++-- HP2100/hp2100_dr.c | 729 +-- HP2100/hp2100_ds.c | 1951 +++--- HP2100/hp2100_fp.c | 365 +- HP2100/hp2100_fp1.c | 383 +- HP2100/hp2100_fp1.h | 12 +- HP2100/hp2100_ipl.c | 602 +- HP2100/hp2100_lps.c | 504 +- HP2100/hp2100_lpt.c | 300 +- HP2100/hp2100_ms.c | 1229 ++-- HP2100/hp2100_mt.c | 696 ++- HP2100/hp2100_mux.c | 1014 ++-- HP2100/hp2100_stddev.c | 1105 ++-- HP2100/hp2100_sys.c | 654 ++- I1401/i1401_cd.c | 344 +- I1401/i1401_cpu.c | 2330 ++++---- I1401/i1401_dat.h | 74 +- I1401/i1401_defs.h | 424 +- I1401/i1401_doc.txt | 13 +- I1401/i1401_dp.c | 689 ++- I1401/i1401_iq.c | 163 +- I1401/i1401_lp.c | 277 +- I1401/i1401_mt.c | 413 +- I1401/i1401_sys.c | 384 +- I1620/i1620_cd.c | 413 +- I1620/i1620_cpu.c | 2381 ++++---- I1620/i1620_defs.h | 317 +- I1620/i1620_doc.txt | 8 +- I1620/i1620_dp.c | 538 +- I1620/i1620_fp.c | 409 +- I1620/i1620_lp.c | 326 +- I1620/i1620_pt.c | 470 +- I1620/i1620_sys.c | 722 +-- I1620/i1620_tty.c | 361 +- Ibm1130/readme1130.txt | 2 +- Interdata/id16_cpu.c | 2758 ++++----- Interdata/id16_dboot.c | 84 +- Interdata/id16_sys.c | 543 +- Interdata/id32_cpu.c | 3315 ++++++----- Interdata/id32_dboot.c | 91 +- Interdata/id32_sys.c | 668 ++- Interdata/id_defs.h | 656 +-- Interdata/id_doc.txt | 9 +- Interdata/id_dp.c | 720 +-- Interdata/id_fd.c | 651 +- Interdata/id_fp.c | 585 +- Interdata/id_idc.c | 987 ++-- Interdata/id_io.c | 519 +- Interdata/id_lp.c | 332 +- Interdata/id_mt.c | 631 +- Interdata/id_pas.c | 715 +-- Interdata/id_pt.c | 454 +- Interdata/id_tt.c | 302 +- Interdata/id_ttp.c | 283 +- Interdata/id_uvc.c | 388 +- LGP/lgp_cpu.c | 753 +-- LGP/lgp_defs.h | 147 +- LGP/lgp_doc.txt | 4 +- LGP/lgp_stddev.c | 694 ++- LGP/lgp_sys.c | 352 +- NOVA/eclipse.txt | 2 +- NOVA/eclipse_cpu.c | 7861 ++++++++++++------------- NOVA/eclipse_tt.c | 535 +- NOVA/nova_clk.c | 150 +- NOVA/nova_cpu.c | 1374 ++--- NOVA/nova_defs.h | 397 +- NOVA/nova_dkp.c | 1137 ++-- NOVA/nova_doc.txt | 8 +- NOVA/nova_dsk.c | 333 +- NOVA/nova_lp.c | 112 +- NOVA/nova_mta.c | 825 +-- NOVA/nova_plt.c | 114 +- NOVA/nova_pt.c | 217 +- NOVA/nova_qty.c | 1730 +++--- NOVA/nova_sys.c | 1137 ++-- NOVA/nova_tt.c | 204 +- NOVA/nova_tt1.c | 311 +- PDP1/pdp1_cpu.c | 1333 +++-- PDP1/pdp1_defs.h | 164 +- PDP1/pdp1_doc.txt | 8 +- PDP1/pdp1_drm.c | 418 +- PDP1/pdp1_dt.c | 1320 +++-- PDP1/pdp1_lp.c | 232 +- PDP1/pdp1_stddev.c | 648 +- PDP1/pdp1_sys.c | 539 +- PDP10/pdp10_cpu.c | 2639 +++++---- PDP10/pdp10_defs.h | 1062 ++-- PDP10/pdp10_doc.txt | 12 +- PDP10/pdp10_fe.c | 113 +- PDP10/pdp10_ksio.c | 585 +- PDP10/pdp10_lp20.c | 804 +-- PDP10/pdp10_mdfp.c | 775 +-- PDP10/pdp10_pag.c | 650 +- PDP10/pdp10_rp.c | 1771 +++--- PDP10/pdp10_sys.c | 692 ++- PDP10/pdp10_tim.c | 203 +- PDP10/pdp10_tu.c | 1721 +++--- PDP10/pdp10_xtnd.c | 901 +-- PDP11/pdp11_cis.c | 1627 ++--- PDP11/pdp11_cpu.c | 4100 +++++++------ PDP11/pdp11_cpumod.c | 1224 ++-- PDP11/pdp11_cpumod.h | 358 +- PDP11/pdp11_defs.h | 1233 ++-- PDP11/pdp11_doc.txt | 20 +- PDP11/pdp11_dz.c | 748 +-- PDP11/pdp11_fp.c | 1376 +++-- PDP11/pdp11_hk.c | 1665 +++--- PDP11/pdp11_io.c | 681 ++- PDP11/pdp11_lp.c | 162 +- PDP11/pdp11_mscp.h | 698 +-- PDP11/pdp11_pclk.c | 262 +- PDP11/pdp11_pt.c | 328 +- PDP11/pdp11_rh.c | 886 +-- PDP11/pdp11_rk.c | 990 ++-- PDP11/pdp11_rl.c | 871 +-- PDP11/pdp11_rp.c | 1380 ++--- PDP11/pdp11_rq.c | 3164 +++++----- PDP11/pdp11_rx.c | 718 +-- PDP11/pdp11_ry.c | 954 +-- PDP11/pdp11_stddev.c | 446 +- PDP11/pdp11_sys.c | 1211 ++-- PDP11/pdp11_tc.c | 1638 +++--- PDP11/pdp11_tm.c | 891 +-- PDP11/pdp11_tq.c | 2506 ++++---- PDP11/pdp11_ts.c | 1425 ++--- PDP11/pdp11_tu.c | 1251 ++-- PDP11/pdp11_uqssp.h | 172 +- PDP11/pdp11_vh.c | 75 +- PDP11/pdp11_xq.c | 23 +- PDP11/pdp11_xq.h | 215 +- PDP11/pdp11_xq_bootrom.h | 6 +- PDP11/pdp11_xu.c | 15 +- PDP11/pdp11_xu.h | 386 +- PDP18B/pdp18b_cpu.c | 2651 +++++---- PDP18B/pdp18b_defs.h | 679 ++- PDP18B/pdp18b_diag.txt | 2 +- PDP18B/pdp18b_doc.txt | 13 +- PDP18B/pdp18b_drm.c | 229 +- PDP18B/pdp18b_dt.c | 1937 +++--- PDP18B/pdp18b_fpp.c | 881 +-- PDP18B/pdp18b_lp.c | 894 +-- PDP18B/pdp18b_mt.c | 637 +- PDP18B/pdp18b_rb.c | 296 +- PDP18B/pdp18b_rf.c | 389 +- PDP18B/pdp18b_rp.c | 544 +- PDP18B/pdp18b_stddev.c | 1091 ++-- PDP18B/pdp18b_sys.c | 893 +-- PDP18B/pdp18b_tt1.c | 397 +- PDP8/pdp8_clk.c | 154 +- PDP8/pdp8_cpu.c | 2063 +++---- PDP8/pdp8_defs.h | 255 +- PDP8/pdp8_df.c | 387 +- PDP8/pdp8_doc.txt | 9 +- PDP8/pdp8_dt.c | 1662 +++--- PDP8/pdp8_lp.c | 160 +- PDP8/pdp8_mt.c | 795 +-- PDP8/pdp8_pt.c | 292 +- PDP8/pdp8_rf.c | 479 +- PDP8/pdp8_rk.c | 528 +- PDP8/pdp8_rl.c | 837 +-- PDP8/pdp8_rx.c | 1020 ++-- PDP8/pdp8_sys.c | 596 +- PDP8/pdp8_td.c | 1051 ++-- PDP8/pdp8_tsc.c | 155 +- PDP8/pdp8_tt.c | 285 +- PDP8/pdp8_ttx.c | 471 +- S3/s3_cd.c | 539 +- S3/s3_cpu.c | 2074 +++---- S3/s3_defs.h | 98 +- S3/s3_disk.c | 1086 ++-- S3/s3_lp.c | 464 +- S3/s3_pkb.c | 347 +- S3/s3_sys.c | 1472 ++--- SDS/sds_cpu.c | 1806 +++--- SDS/sds_defs.h | 582 +- SDS/sds_doc.txt | 13 +- SDS/sds_drm.c | 362 +- SDS/sds_dsk.c | 417 +- SDS/sds_io.c | 950 +-- SDS/sds_lp.c | 335 +- SDS/sds_mt.c | 563 +- SDS/sds_mux.c | 560 +- SDS/sds_rad.c | 331 +- SDS/sds_stddev.c | 618 +- SDS/sds_sys.c | 584 +- VAX/vax_cis.c | 2083 +++---- VAX/vax_cmode.c | 1632 +++--- VAX/vax_cpu.c | 4331 +++++++------- VAX/vax_cpu1.c | 1852 +++--- VAX/vax_defs.h | 963 +-- VAX/vax_doc.txt | 10 +- VAX/vax_fpa.c | 1323 +++-- VAX/vax_io.c | 1031 ++-- VAX/vax_mmu.c | 529 +- VAX/vax_octa.c | 1237 ++-- VAX/vax_stddev.c | 311 +- VAX/vax_sys.c | 2074 +++---- VAX/vax_syscm.c | 725 +-- VAX/vax_sysdev.c | 1442 +++-- VAX/vax_syslist.c | 113 +- VAX/vaxmod_defs.h | 584 +- descrip.mms | 2 +- scp.c | 4347 +++++++------- scp.h | 32 +- sim_console.c | 709 +-- sim_console.h | 14 +- sim_defs.h | 653 +-- sim_ether.c | 83 +- sim_ether.h | 84 +- sim_fio.c | 171 +- sim_fio.h | 17 +- sim_rev.h | 2075 +++---- sim_sock.c | 187 +- sim_sock.h | 62 +- sim_tape.c | 547 +- sim_tape.h | 92 +- sim_timer.c | 180 +- sim_timer.h | 14 +- sim_tmxr.c | 655 ++- sim_tmxr.h | 80 +- simh_doc.txt | 44 +- simh_faq.txt | 47 +- simh_swre.txt | 8 +- 257 files changed, 107140 insertions(+), 97195 deletions(-) delete mode 100644 0readme_34.txt create mode 100644 0readme_35.txt diff --git a/0readme_34.txt b/0readme_34.txt deleted file mode 100644 index 0c13058c..00000000 --- a/0readme_34.txt +++ /dev/null @@ -1,38 +0,0 @@ -Notes For V3.4-0 - -The memory layout for the Interdata simulators has been changed. -Do not use Interdata SAVE files from prior revisions with V3.4. - -1. New Features in 3.4 - -1.1 SCP and Libraries - -- Revised interpretation of fprint_sym, fparse_sym returns -- Revised syntax for SET DEBUG -- DO command nesting allowed to ten levels - -1.2 Interdata - -- Revised memory model to be 16b instead of 8b - -1.3 HP2100 - -- Added Fast FORTRAN Processor instructions -- Added SET OFFLINE/ONLINE and SET UNLOAD/LOAD commands to tapes and disks - -2. Bugs Fixed in 3.4-0 - -2.1 Interdata - -- Fixed bug in show history routine (from Mark Hittinger) -- Fixed bug in initial memory allocation - -2.2 PDP-10 - -- Fixed TU bug, ERASE and WREOF should not clear done (reported by - Rich Alderson) -- Fixed TU error reporting - -2.3 PDP-11 - -- Fixed TU error reporting diff --git a/0readme_35.txt b/0readme_35.txt new file mode 100644 index 00000000..705600aa --- /dev/null +++ b/0readme_35.txt @@ -0,0 +1,70 @@ +Notes For V3.5-0 + +The source set has been extensively overhauled. For correct +viewing, set Visual C++ or Emacs to have tab stops every 4 +characters. + +1. New Features in 3.4-1 + +1.1 All Ethernet devices + +- Added Windows user-defined adapter names (from Timothe Litt) + +1.2 Interdata, SDS, HP, PDP-8, PDP-18b terminal multiplexors + +- Added support for SET n DISCONNECT + +1.3 VAX + +- Added latent QDSS support +- Revised autoconfigure to handle QDSS + +1.4 PDP-11 + +- Revised autoconfigure to handle more casees + +2. Bugs Fixed in 3.4-1 + +2.1 SCP and libraries + +- Trim trailing spaces on all input (for example, attach file names) +- Fixed sim_sock spurious SIGPIPE error in Unix/Linux +- Fixed sim_tape misallocation of TPC map array for 64b simulators + +2.2 1401 + +- Fixed bug, CPU reset was clearing SSB through SSG + +2.3 PDP-11 + +- Fixed bug in VH vector display routine +- Fixed XU runt packet processing (found by Tim Chapman) + +2.4 Interdata + +- Fixed bug in SHOW PAS CONN/STATS +- Fixed potential integer overflow exception in divide + +2.5 SDS + +- Fixed bug in SHOW MUX CONN/STATS + +2.6 HP + +- Fixed bug in SHOW MUX CONN/STATS + +2.7 PDP-8 + +- Fixed bug in SHOW TTIX CONN/STATS +- Fixed bug in SET/SHOW TTOXn LOG + +2.8 PDP-18b + +- Fixed bug in SHOW TTIX CONN/STATS +- Fixed bug in SET/SHOW TTOXn LOG + +2.9 Nova, Eclipse + +- Fixed potential integer overflow exception in divide + + diff --git a/0readme_ethernet.txt b/0readme_ethernet.txt index cff3c22e..4cc74fb3 100644 --- a/0readme_ethernet.txt +++ b/0readme_ethernet.txt @@ -41,7 +41,7 @@ route TAP devices for you. 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 + http://www.winpcap.org. This package for windows simulates the libpcap package that is freely available for un*x systems. 2. You must *install* the WinPCAP runtime package. diff --git a/ALTAIR/altair_cpu.c b/ALTAIR/altair_cpu.c index 1977d0e2..740d66f7 100644 --- a/ALTAIR/altair_cpu.c +++ b/ALTAIR/altair_cpu.c @@ -1,6 +1,6 @@ /* altair_cpu.c: MITS Altair Intel 8080 CPU simulator - Copyright (c) 1997-2003, Charles E. Owen + Copyright (c) 1997-2005, 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"), @@ -19,35 +19,34 @@ 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 + 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 + cpu 8080 CPU - 08-Oct-02 RMS Tied off spurious compiler warnings + 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 + 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. + + 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. @@ -56,9 +55,9 @@ 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) + 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 @@ -72,43 +71,43 @@ 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 + 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) +#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 */ +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 */ +int32 PCX; /* External view of PC */ extern int32 sim_int_char; -extern int32 sim_brk_types, sim_brk_dflt, sim_brk_summ; /* breakpoint info */ +extern int32 sim_brk_types, sim_brk_dflt, sim_brk_summ; /* breakpoint info */ /* function prototypes */ @@ -142,78 +141,79 @@ 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)(); + 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 */ - +{&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, + 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 */ @@ -248,157 +248,159 @@ int32 bootrom[256] = { /* CPU data structures - cpu_dev CPU device descriptor - cpu_unit CPU unit descriptor - cpu_reg CPU register list - cpu_mod CPU modifiers list + 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) }; +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 } }; + { 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 } }; + { 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 }; - + "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; + 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; + PC = saved_PC & ADDRMASK; /* load local PC */ + C = C & 0200000; + reason = 0; - /* Main instruction fetch/decode loop */ + /* Main instruction fetch/decode loop */ - while (reason == 0) { /* loop until halted */ - if (sim_interval <= 0) { /* check clock queue */ - if (reason = sim_process_event ()) break; - } + while (reason == 0) { /* loop until halted */ + if (sim_interval <= 0) { /* check clock queue */ + if (reason = sim_process_event ()) break; + } - if (int_req > 0) { /* interrupt? */ + 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 */ + } /* end interrupt */ - if (sim_brk_summ && - sim_brk_test (PC, SWMASK ('E'))) { /* breakpoint? */ - reason = STOP_IBKPT; /* stop simulation */ - break; - } + 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; + 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 */ + IR = OP = M[PC]; /* fetch instruction */ - PC = (PC + 1) & ADDRMASK; /* increment PC */ + PC = (PC + 1) & ADDRMASK; /* increment PC */ - sim_interval--; + sim_interval--; - if (OP == 0166) { /* HLT Instruction*/ - reason = STOP_HALT; + if (OP == 0166) { /* HLT Instruction*/ + reason = STOP_HALT; PC--; - continue; - } + continue; + } - /* Handle below all operations which refer to registers or - register pairs. After that, a large switch statement - takes care of all other opcodes */ + /* 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; + 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; - } + 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); + 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) { + 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]; @@ -408,21 +410,21 @@ int32 sim_instr (void) SP--; M[SP] = PC & 0xff; PC = (hi << 8) + lo; - } else { - PC += 2; - } - continue; - } - if ((OP & 0xC7) == 0xC0) { /* RET */ - if (cond((OP >> 3) & 0x07) == 1) { + } 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 */ + } + continue; + } + if ((OP & 0xC7) == 0xC7) { /* RST */ SP--; M[SP] = (PC >> 8) & 0xff; SP--; @@ -431,229 +433,229 @@ int32 sim_instr (void) continue; } - if ((OP & 0xCF) == 0xC5) { /* PUSH */ - DAR = getpush((OP >> 4) & 0x03); + 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]; + 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); + if ((OP & 0xF8) == 0x80) { /* ADD */ + A += getreg(OP & 0x07); setarith(A); - A = A & 0xFF; - continue; + A = A & 0xFF; + continue; } - if ((OP & 0xF8) == 0x88) { /* ADC */ - carry = 0; + if ((OP & 0xF8) == 0x88) { /* ADC */ + carry = 0; if (C) carry = 1; - A += getreg(OP & 0x07); + A += getreg(OP & 0x07); A += carry; setarith(A); - A = A & 0xFF; - continue; + A = A & 0xFF; + continue; } - if ((OP & 0xF8) == 0x90) { /* SUB */ - A -= getreg(OP & 0x07); + if ((OP & 0xF8) == 0x90) { /* SUB */ + A -= getreg(OP & 0x07); setarith(A); - A = A & 0xFF; - continue; + A = A & 0xFF; + continue; } - if ((OP & 0xF8) == 0x98) { /* SBB */ - carry = 0; + if ((OP & 0xF8) == 0x98) { /* SBB */ + carry = 0; if (C) carry = 1; - A -= (getreg(OP & 0x07)) + carry ; + A -= (getreg(OP & 0x07)) + carry ; setarith(A); - A = A & 0xFF; - continue; + A = A & 0xFF; + continue; } - if ((OP & 0xC7) == 0x04) { /* INR */ - DAR = getreg((OP >> 3) & 0x07); + if ((OP & 0xC7) == 0x04) { /* INR */ + DAR = getreg((OP >> 3) & 0x07); DAR++; setinc(DAR); - DAR = DAR & 0xFF; + DAR = DAR & 0xFF; putreg((OP >> 3) & 0x07, DAR); - continue; + continue; } - if ((OP & 0xC7) == 0x05) { /* DCR */ - DAR = getreg((OP >> 3) & 0x07); + if ((OP & 0xC7) == 0x05) { /* DCR */ + DAR = getreg((OP >> 3) & 0x07); DAR--; setinc(DAR); - DAR = DAR & 0xFF; + DAR = DAR & 0xFF; putreg((OP >> 3) & 0x07, DAR); - continue; + continue; } - if ((OP & 0xCF) == 0x03) { /* INX */ - DAR = getpair((OP >> 4) & 0x03); + if ((OP & 0xCF) == 0x03) { /* INX */ + DAR = getpair((OP >> 4) & 0x03); DAR++; - DAR = DAR & 0xFFFF; + DAR = DAR & 0xFFFF; putpair((OP >> 4) & 0x03, DAR); - continue; + continue; } - if ((OP & 0xCF) == 0x0B) { /* DCX */ - DAR = getpair((OP >> 4) & 0x03); + if ((OP & 0xCF) == 0x0B) { /* DCX */ + DAR = getpair((OP >> 4) & 0x03); DAR--; - DAR = DAR & 0xFFFF; + DAR = DAR & 0xFFFF; putpair((OP >> 4) & 0x03, DAR); - continue; + continue; } - if ((OP & 0xCF) == 0x09) { /* DAD */ - HL += getpair((OP >> 4) & 0x03); + if ((OP & 0xCF) == 0x09) { /* DAD */ + HL += getpair((OP >> 4) & 0x03); C = 0; if (HL & 0x10000) - C = 0200000; - HL = HL & 0xFFFF; - continue; + C = 0200000; + HL = HL & 0xFFFF; + continue; } - if ((OP & 0xF8) == 0xA0) { /* ANA */ - A &= getreg(OP & 0x07); + 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); + 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); + continue; + } + if ((OP & 0xF8) == 0xB0) { /* ORA */ + A |= getreg(OP & 0x07); C = 0; setlogical(A); A &= 0xFF; - continue; - } + continue; + } - /* The Big Instruction Decode Switch */ + /* The Big Instruction Decode Switch */ - switch (IR) { + switch (IR) { - /* Logical instructions */ + /* Logical instructions */ - case 0376: { /* CPI */ - DAR = A & 0xFF; - DAR -= M[PC]; + 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++; + 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; + PC = (hi << 8) + lo; break; } - case 0311: { /* RET */ - PC = M[SP]; + case 0311: { /* RET */ + PC = M[SP]; SP++; PC |= (M[SP] << 8) & 0xff00; SP++; - break; + break; } - /* Data Transfer Group */ + /* 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; + 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; + 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; + case 0353: { /* XCHG */ + DAR = HL; HL = DE; DE = DAR; break; @@ -661,59 +663,59 @@ int32 sim_instr (void) /* Arithmetic Group */ - case 0306: { /* ADI */ - A += M[PC]; + case 0306: { /* ADI */ + A += M[PC]; PC++; setarith(A); - A = A & 0xFF; - break; + A = A & 0xFF; + break; } - case 0316: { /* ACI */ - carry = 0; + case 0316: { /* ACI */ + carry = 0; if (C) carry = 1; - A += M[PC]; + A += M[PC]; A += carry; PC++; setarith(A); - A = A & 0xFF; - break; + A = A & 0xFF; + break; } - case 0326: { /* SUI */ - A -= M[PC]; + case 0326: { /* SUI */ + A -= M[PC]; PC++; setarith(A); - A = A & 0xFF; - break; + A = A & 0xFF; + break; } - case 0336: { /* SBI */ - carry = 0; + case 0336: { /* SBI */ + carry = 0; if (C) carry = 1; - A -= (M[PC] + carry); + A -= (M[PC] + carry); PC++; setarith(A); - A = A & 0xFF; - break; + A = A & 0xFF; + break; } - case 047: { /* DAA */ - DAR = A & 0x0F; + case 047: { /* DAA */ + DAR = A & 0x0F; if (DAR > 9 || AC > 0) { - DAR += 6; + DAR += 6; A &= 0xF0; - A |= DAR & 0x0F; + A |= DAR & 0x0F; if (DAR & 0x10) - AC = 0200000; + AC = 0200000; else AC = 0; } DAR = (A >> 4) & 0x0F; if (DAR > 9 || AC > 0) { - DAR += 6; + DAR += 6; if (AC) DAR++; A &= 0x0F; A |= (DAR << 4); } if ((DAR << 4) & 0x100) - C = 0200000; + C = 0200000; else C = 0; if (A & 0x80) { @@ -726,116 +728,116 @@ int32 sim_instr (void) else Z = 0; parity(A); - A = A & 0xFF; - break; + A = A & 0xFF; + break; } - case 07: { /* RLC */ + case 07: { /* RLC */ C = 0; C = (A << 9) & 0200000; - A = (A << 1) & 0xFF; + A = (A << 1) & 0xFF; if (C) - A |= 0x01; + A |= 0x01; break; } - case 017: { /* RRC */ + case 017: { /* RRC */ C = 0; if ((A & 0x01) == 1) - C |= 0200000; - A = (A >> 1) & 0xFF; + C |= 0200000; + A = (A >> 1) & 0xFF; if (C) - A |= 0x80; + A |= 0x80; break; } - case 027: { /* RAL */ - DAR = C; + case 027: { /* RAL */ + DAR = C; C = 0; C = (A << 9) & 0200000; - A = (A << 1) & 0xFF; + A = (A << 1) & 0xFF; if (DAR) - A |= 1; + A |= 1; else - A &= 0xFE; + A &= 0xFE; break; } - case 037: { /* RAR */ - DAR = C; + case 037: { /* RAR */ + DAR = C; C = 0; if ((A & 0x01) == 1) - C |= 0200000; - A = (A >> 1) & 0xFF; + C |= 0200000; + A = (A >> 1) & 0xFF; if (DAR) - A |= 0x80; + A |= 0x80; else - A &= 0x7F; + A &= 0x7F; break; } - case 057: { /* CMA */ - A = ~ A; + case 057: { /* CMA */ + A = ~ A; A &= 0xFF; break; } - case 077: { /* CMC */ - C = ~ C; + case 077: { /* CMC */ + C = ~ C; C &= 0200000; break; } - case 067: { /* STC */ - C = 0200000; + case 067: { /* STC */ + C = 0200000; break; } - /* Stack, I/O & Machine Control Group */ + /* Stack, I/O & Machine Control Group */ - case 0: { /* NOP */ - break; + case 0: { /* NOP */ + break; } - case 0343: { /* XTHL */ - lo = M[SP]; + 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; + break; } - case 0371: { /* SPHL */ - SP = HL; - break; + case 0371: { /* SPHL */ + SP = HL; + break; } - case 0373: { /* EI */ - INTE = 0200000; - break; + case 0373: { /* EI */ + INTE = 0200000; + break; } - case 0363: { /* DI */ - INTE = 0; - break; + case 0363: { /* DI */ + INTE = 0; + break; } - case 0333: { /* IN */ - DAR = M[PC] & 0xFF; + case 0333: { /* IN */ + DAR = M[PC] & 0xFF; PC++; if (DAR == 0xFF) { - A = (SR >> 8) & 0xFF; + A = (SR >> 8) & 0xFF; } else { - A = dev_table[DAR].routine(0, 0); + A = dev_table[DAR].routine(0, 0); } - break; + break; } - case 0323: { /* OUT */ - DAR = M[PC] & 0xFF; + case 0323: { /* OUT */ + DAR = M[PC] & 0xFF; PC++; dev_table[DAR].routine(1, A); - break; + break; } - default: { - if (cpu_unit.flags & UNIT_OPSTOP) { - reason = STOP_OPCODE; + default: { + if (cpu_unit.flags & UNIT_OPSTOP) { + reason = STOP_OPCODE; PC--; } - break; - } + break; + } } } - + /* Simulation halted */ saved_PC = PC; @@ -845,35 +847,33 @@ 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); + case 0: + if (Z == 0) return (1); break; case 1: - if (Z != 0) return (1); + if (Z != 0) return (1); break; case 2: - if (C == 0) return (1); + if (C == 0) return (1); break; case 3: - if (C != 0) return (1); + if (C != 0) return (1); break; case 4: - if (P == 0) return (1); + if (P == 0) return (1); break; case 5: - if (P != 0) return (1); + if (P != 0) return (1); break; case 6: - if (S == 0) return (1); + if (S == 0) return (1); break; case 7: - if (S != 0) return (1); + if (S != 0) return (1); break; default: - break; + break; } return (0); } @@ -884,27 +884,27 @@ int32 cond(int32 con) void setarith(int32 reg) { - int32 bc = 0; + int32 bc = 0; - if (reg & 0x100) - C = 0200000; + if (reg & 0x100) + C = 0200000; else - C = 0; - if (reg & 0x80) { - bc++; - S = 0200000; + C = 0; + if (reg & 0x80) { + bc++; + S = 0200000; } else { S = 0; } if ((reg & 0xff) == 0) - Z = 0200000; + Z = 0200000; else Z = 0; AC = 0; if (cpu_unit.flags & UNIT_CHIP) { - P = 0; /* parity is zero for *all* arith ops on Z80 */ + P = 0; /* parity is zero for *all* arith ops on Z80 */ } else { - parity(reg); + parity(reg); } } @@ -915,13 +915,13 @@ void setarith(int32 reg) void setlogical(int32 reg) { C = 0; - if (reg & 0x80) { - S = 0200000; + if (reg & 0x80) { + S = 0200000; } else { S = 0; } if ((reg & 0xff) == 0) - Z = 0200000; + Z = 0200000; else Z = 0; AC = 0; @@ -934,7 +934,7 @@ void setlogical(int32 reg) void parity(int32 reg) { - int32 bc = 0; + int32 bc = 0; if (reg & 0x01) bc++; if (reg & 0x02) bc++; @@ -954,45 +954,45 @@ void parity(int32 reg) void setinc(int32 reg) { - int32 bc = 0; + int32 bc = 0; - if (reg & 0x80) { - bc++; - S = 0200000; + if (reg & 0x80) { + bc++; + S = 0200000; } else { S = 0; } if ((reg & 0xff) == 0) - Z = 0200000; + Z = 0200000; else Z = 0; if (cpu_unit.flags & UNIT_CHIP) { - P = 0; /* parity is zero for *all* arith ops on Z80 */ + P = 0; /* parity is zero for *all* arith ops on Z80 */ } else { - parity(reg); + parity(reg); } } /* Get an 8080 register and return it */ int32 getreg(int32 reg) { - switch (reg) { - case 0: - return ((BC >>8) & 0x00ff); + switch (reg) { + case 0: + return ((BC >>8) & 0x00ff); case 1: - return (BC & 0x00FF); + return (BC & 0x00FF); case 2: - return ((DE >>8) & 0x00ff); + return ((DE >>8) & 0x00ff); case 3: - return (DE & 0x00ff); + return (DE & 0x00ff); case 4: - return ((HL >>8) & 0x00ff); + return ((HL >>8) & 0x00ff); case 5: - return (HL & 0x00ff); + return (HL & 0x00ff); case 6: return (M[HL]); case 7: - return (A); + return (A); default: break; } @@ -1002,36 +1002,36 @@ int32 getreg(int32 reg) /* Put a value into an 8080 register from memory */ void putreg(int32 reg, int32 val) { - switch (reg) { - case 0: - BC = BC & 0x00FF; + switch (reg) { + case 0: + BC = BC & 0x00FF; BC = BC | (val <<8); break; case 1: - BC = BC & 0xFF00; + BC = BC & 0xFF00; BC = BC | val; break; case 2: - DE = DE & 0x00FF; + DE = DE & 0x00FF; DE = DE | (val <<8); break; case 3: - DE = DE & 0xFF00; + DE = DE & 0xFF00; DE = DE | val; break; case 4: - HL = HL & 0x00FF; + HL = HL & 0x00FF; HL = HL | (val <<8); break; case 5: - HL = HL & 0xFF00; + HL = HL & 0xFF00; HL = HL | val; break; case 6: - M[HL] = val & 0xff; + M[HL] = val & 0xff; break; case 7: - A = val & 0xff; + A = val & 0xff; default: break; } @@ -1040,15 +1040,15 @@ void putreg(int32 reg, int32 val) /* Return the value of a selected register pair */ int32 getpair(int32 reg) { - switch (reg) { - case 0: - return (BC); + switch (reg) { + case 0: + return (BC); case 1: - return (DE); + return (DE); case 2: - return (HL); + return (HL); case 3: - return (SP); + return (SP); default: break; } @@ -1059,24 +1059,24 @@ int32 getpair(int32 reg) format where 3 means A& flags, not SP */ int32 getpush(int32 reg) { - int32 stat; + int32 stat; - switch (reg) { - case 0: - return (BC); + switch (reg) { + case 0: + return (BC); case 1: - return (DE); + return (DE); case 2: - return (HL); + return (HL); case 3: - stat = A << 8; + stat = A << 8; if (S) stat |= 0x80; if (Z) stat |= 0x40; if (AC) stat |= 0x10; if (P) stat |= 0x04; - stat |= 0x02; + stat |= 0x02; if (C) stat |= 0x01; - return (stat); + return (stat); default: break; } @@ -1088,25 +1088,25 @@ int32 getpush(int32 reg) format where 3 means A& flags, not SP */ void putpush(int32 reg, int32 data) { - switch (reg) { - case 0: - BC = data; + switch (reg) { + case 0: + BC = data; break; case 1: - DE = data; + DE = data; break; case 2: - HL = data; + HL = data; break; case 3: - A = (data >> 8) & 0xff; + 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; + break; default: break; } @@ -1116,18 +1116,18 @@ void putpush(int32 reg, int32 data) /* Put a value into an 8080 register pair */ void putpair(int32 reg, int32 val) { - switch (reg) { - case 0: - BC = val; + switch (reg) { + case 0: + BC = val; break; case 1: - DE = val; + DE = val; break; case 2: - HL = val; + HL = val; break; case 3: - SP = val; + SP = val; break; default: break; @@ -1160,9 +1160,9 @@ return SCPE_OK; t_stat cpu_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw) { - if (addr >= MEMSIZE) return SCPE_NXM; + if (addr >= MEMSIZE) return SCPE_NXM; M[addr] = val & 0377; - return SCPE_OK; + return SCPE_OK; } t_stat cpu_set_size (UNIT *uptr, int32 val, char *cptr, void *desc) @@ -1171,10 +1171,10 @@ int32 mc = 0; uint32 i; if ((val <= 0) || (val > MAXMEMSIZE) || ((val & 07777) != 0)) - return SCPE_ARG; + 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; + return SCPE_OK; MEMSIZE = val; for (i = MEMSIZE; i < MAXMEMSIZE; i++) M[i] = 0; return SCPE_OK; @@ -1182,8 +1182,8 @@ return SCPE_OK; int32 nulldev(int32 flag, int32 data) { - if (flag == 0) - return (0377); - return 0; + if (flag == 0) + return (0377); + return 0; } diff --git a/ALTAIR/altair_defs.h b/ALTAIR/altair_defs.h index 5786247e..ca8444a9 100644 --- a/ALTAIR/altair_defs.h +++ b/ALTAIR/altair_defs.h @@ -1,6 +1,6 @@ /* altair_defs.h: MITS Altair simulator definitions - Copyright (c) 1997-2003, Charles E. Owen + Copyright (c) 1997-2005, 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"), @@ -19,24 +19,24 @@ 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 + 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 */ +#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 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_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 index 5ae54cf5..4218f1d7 100644 --- a/ALTAIR/altair_dsk.c +++ b/ALTAIR/altair_dsk.c @@ -1,6 +1,6 @@ /* altair_dsk.c: MITS Altair 88-DISK Simulator - Copyright (c) 1997-2003, Charles E. Owen + Copyright (c) 1997-2005, 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"), @@ -19,11 +19,11 @@ 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 + 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 + 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. @@ -31,15 +31,15 @@ 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 - ------- ---- -------- + 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 + 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): @@ -48,7 +48,7 @@ +---+---+---+---+---+---+---+---+ C = If this bit is 1, the disk controller selected by 'device' is - cleared. If the bit is zero, 'device' is selected as the + 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. @@ -80,8 +80,8 @@ 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 + 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 @@ -100,9 +100,9 @@ X = Not used Sector number = binary of the sector number currently under the - head, 0-31. + head, 0-31. T = Sector True, is a 1 when the sector is positioned to read or - write. + write. */ @@ -110,8 +110,8 @@ #include "altair_defs.h" -#define UNIT_V_ENABLE (UNIT_V_UF + 0) /* Write Enable */ -#define UNIT_ENABLE (1 << UNIT_V_ENABLE) +#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 @@ -128,41 +128,43 @@ extern int32 PCX; /* Global data on status */ -int32 cur_disk = 8; /* Currently selected drive */ +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 */ +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 */ +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) } - }; + { 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 } }; + { 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 }; + "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 */ @@ -181,19 +183,19 @@ cur_disk = 0; return SCPE_OK; } -/* I/O instruction handlers, called from the CPU module when an - IN or OUT instruction is issued. +/* 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 + 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 +/* 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 @@ -203,28 +205,28 @@ return SCPE_OK; int32 dsk10(int32 io, int32 data) { - if (io == 0) { /* IN: return flags */ - return ((~cur_flags[cur_disk]) & 0xFF); /* Return the COMPLEMENT! */ + 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(); + writebuf(); /*printf("\n[%o] OUT 10: %x", PCX, data);*/ cur_disk = data & 0x0F; if (data & 0x80) { - cur_flags[cur_disk] = 0; /* Disable drive */ + 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_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 */ + cur_flags[cur_disk] |= 0x40; /* track 0 if there */ return (0); } @@ -232,74 +234,74 @@ int32 dsk10(int32 io, int32 data) int32 dsk11(int32 io, int32 data) { - int32 stat; + 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? */ + 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_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 */ + 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 */ + return (0); /* head not loaded - return 0 */ } } /* Drive functions */ if (cur_disk > 7) - return (0); /* no drive selected - can do nothin */ + 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 (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_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 (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 */ + cur_track[cur_disk] = 0; + cur_flags[cur_disk] |= 0x40; /* track 0 if there */ } - if (dirty == 1) - writebuf(); + if (dirty == 1) + writebuf(); cur_sect[cur_disk] = 0377; cur_byte[cur_disk] = 0377; } if (dirty == 1) - writebuf(); + 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 & 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 */ + 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 */ + if (data & 0x80) { /* write sequence start */ cur_byte[cur_disk] = 0; - cur_flags[cur_disk] |= 0x01; /* enter new write data on */ + cur_flags[cur_disk] |= 0x01; /* enter new write data on */ } return 0; } @@ -308,19 +310,19 @@ int32 dsk11(int32 io, int32 data) int32 dsk12(int32 io, int32 data) { - static int32 rtn, i; + 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); + 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]);*/ + cur_sect[cur_disk]);*/ pos = DSK_TRACSIZE * cur_track[cur_disk]; pos += DSK_SECTSIZE * cur_sect[cur_disk]; rtn = fseek(uptr -> fileref, pos, 0); @@ -328,9 +330,9 @@ int32 dsk12(int32 io, int32 data) 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; + if (cur_byte[cur_disk] > 136) { + i = cur_byte[cur_disk]; + dskbuf[i] = data & 0xFF; writebuf(); return (0); } @@ -345,21 +347,21 @@ int32 dsk12(int32 io, int32 data) void writebuf() { - long pos; + long pos; int32 rtn, i; - i = cur_byte[cur_disk]; /* null-fill rest of sector if any */ + i = cur_byte[cur_disk]; /* null-fill rest of sector if any */ while (i < 138) { - dskbuf[i] = 0; + 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 */ + 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_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 index 9c212160..abe4cd9a 100644 --- a/ALTAIR/altair_sio.c +++ b/ALTAIR/altair_sio.c @@ -1,6 +1,6 @@ /* altair_sio: MITS Altair serial I/O card - Copyright (c) 1997-2003, Charles E. Owen + Copyright (c) 1997-2005, 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"), @@ -19,11 +19,11 @@ 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 + 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. + 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 @@ -35,13 +35,13 @@ A read of the status port gets the port status: +---+---+---+---+---+---+---+---+ - | X X X X X X O I | + | 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. + 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. + 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. @@ -51,8 +51,8 @@ #include "altair_defs.h" -#define UNIT_V_ANSI (UNIT_V_UF + 0) /* ANSI mode */ -#define UNIT_ANSI (1 << UNIT_V_ANSI) +#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); @@ -61,77 +61,81 @@ 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 */ +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 }; +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 } }; + { 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 } }; + { 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 }; + "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 }; +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 } }; + { 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 }; + "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 }; +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 } }; + { 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 }; + "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 routines to handle simulator functions */ /* service routine - actually gets char & places in buffer */ int32 sio_svc (UNIT *uptr) { - int32 temp; + 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 */ + 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 */ + /* Do any special character handling here */ - sio_unit.pos++; - return SCPE_OK; + sio_unit.pos++; + return SCPE_OK; } @@ -142,7 +146,7 @@ int32 ptr_svc (UNIT *uptr) int32 ptp_svc (UNIT *uptr) { - return SCPE_OK; + return SCPE_OK; } @@ -150,60 +154,60 @@ int32 ptp_svc (UNIT *uptr) 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; + 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; + 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; + 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. +/* 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 + 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) { + if (io == 0) { return (sio_unit.u3); } else { - if (data == 0x03) { /* reset port! */ - sio_unit.u3 = 0x02; + if (data == 0x03) { /* reset port! */ + sio_unit.u3 = 0x02; sio_unit.buf = 0; sio_unit.pos = 0; } - return (0); + return (0); } } int32 sio0d(int32 io, int32 data) { - if (io == 0) { + if (io == 0) { sio_unit.u3 = sio_unit.u3 & 0xFE; return (sio_unit.buf); } else { - sim_putchar(data); + sim_putchar(data); } return 0; } @@ -212,46 +216,46 @@ int32 sio0d(int32 io, int32 data) 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 */ + 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; + if (data == 0x03) { + ptr_unit.u3 = 0; ptr_unit.buf = 0; ptr_unit.pos = 0; - ptp_unit.u3 = 0; + ptp_unit.u3 = 0; ptp_unit.buf = 0; ptp_unit.pos = 0; } - return (0); + return (0); } } int32 sio1d(int32 io, int32 data) { - int32 temp; + int32 temp; UNIT *uptr; - if (io == 0) { - if ((ptr_unit.flags & UNIT_ATT) == 0) /* attached? */ + if (io == 0) { + if ((ptr_unit.flags & UNIT_ATT) == 0) /* attached? */ return 0; if (ptr_unit.u3 != 0) - return 0; + return 0; uptr = ptr_dev.units; - if ((temp = getc(uptr -> fileref)) == EOF) { /* end of file? */ + if ((temp = getc(uptr -> fileref)) == EOF) { /* end of file? */ ptr_unit.u3 = 0x01; return 0; } - ptr_unit.pos++; + ptr_unit.pos++; return (temp & 0xFF); } else { - uptr = ptp_dev.units; - putc(data, uptr -> fileref); - ptp_unit.pos++; + 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 index 00addeac..fa32695a 100644 --- a/ALTAIR/altair_sys.c +++ b/ALTAIR/altair_sys.c @@ -1,6 +1,6 @@ /* altair_sys.c: MITS Altair system interface - Copyright (c) 1997-2003, Charles E. Owen + Copyright (c) 1997-2005, 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"), @@ -19,8 +19,8 @@ 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 + 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. */ @@ -40,12 +40,12 @@ 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 + 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"; @@ -54,81 +54,88 @@ REG *sim_PC = &cpu_reg[0]; int32 sim_emax = 4; -DEVICE *sim_devices[] = { &cpu_dev, &sio_dev, &ptr_dev, - &ptp_dev, &dsk_dev, NULL }; +DEVICE *sim_devices[] = { + &cpu_dev, + &sio_dev, + &ptr_dev, + &ptp_dev, + &dsk_dev, + NULL +}; const char *sim_stop_messages[] = { - "Unknown error", + "Unknown error", "Unknown I/O Instruction", - "HALT instruction", + "HALT instruction", "Breakpoint", - "Invalid Opcode" }; + "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 */ +"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] = { @@ -140,7 +147,7 @@ int32 oplen[256] = { 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. @@ -153,28 +160,28 @@ 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 */ + 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 + *of = output stream + addr = current PC + *val = pointer to values + *uptr = pointer to unit + sw = switches Outputs: - status = error code + status = error code */ int32 fprint_sym (FILE *of, int32 addr, uint32 *val, - UNIT *uptr, int32 sw) + UNIT *uptr, int32 sw) { int32 cflag, c1, c2, inst, adr; @@ -182,42 +189,44 @@ 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; } + 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; } + 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 (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, " "); + 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 + *cptr = pointer to input string + addr = current PC + *uptr = pointer to unit + *val = pointer to output values + sw = switches Outputs: - status = error status + status = error status */ int32 parse_sym (char *cptr, int32 addr, UNIT *uptr, uint32 *val, int32 sw) @@ -226,25 +235,27 @@ int32 cflag, i = 0, j, r; char gbuf[CBUFSIZE]; cflag = (uptr == NULL) || (uptr == &cpu_unit); -while (isspace (*cptr)) cptr++; /* absorb spaces */ +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] = (uint32) cptr[0]; - return SCPE_OK; } + if (cptr[0] == 0) return SCPE_ARG; /* must have 1 char */ + val[0] = (uint32) 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] = ((uint32) cptr[0] << 8) + (uint32) cptr[1]; - return SCPE_OK; } + if (cptr[0] == 0) return SCPE_ARG; /* must have 1 char */ + val[0] = ((uint32) cptr[0] << 8) + (uint32) 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); + if (*cptr == ',' || *cptr == '\0' || + isdigit(*cptr)) + break; + gbuf[i] = toupper(*cptr); cptr++; i++; } @@ -252,9 +263,9 @@ while (1) { /* Allow for RST which has numeric as part of opcode */ if (toupper(gbuf[0]) == 'R' && - toupper(gbuf[1]) == 'S' && + toupper(gbuf[1]) == 'S' && toupper(gbuf[2]) == 'T') { - gbuf[i] = toupper(*cptr); + gbuf[i] = toupper(*cptr); cptr++; i++; } @@ -262,9 +273,9 @@ if (toupper(gbuf[0]) == 'R' && /* Allow for 'MOV' which is only opcode that has comma in it. */ if (toupper(gbuf[0]) == 'M' && - toupper(gbuf[1]) == 'O' && + toupper(gbuf[1]) == 'O' && toupper(gbuf[2]) == 'V') { - gbuf[i] = toupper(*cptr); + gbuf[i] = toupper(*cptr); cptr++; i++; gbuf[i] = toupper(*cptr); @@ -275,25 +286,25 @@ if (toupper(gbuf[0]) == 'M' && /* kill trailing spaces if any */ gbuf[i] = '\0'; for (j = i - 1; gbuf[j] == ' '; j--) { - gbuf[j] = '\0'; + gbuf[j] = '\0'; } /* find opcode in table */ for (j = 0; j < 256; j++) { - if (strcmp(gbuf, opcode[j]) == 0) - break; + if (strcmp(gbuf, opcode[j]) == 0) + break; } -if (j > 255) /* not found */ - return SCPE_ARG; +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; +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 */ +cptr = get_glyph(cptr, gbuf, 0); /* get address */ sscanf(gbuf, "%o", &r); if (oplen[j] == 2) { - val[1] = r & 0xFF; + val[1] = r & 0xFF; return (-1); } val[1] = r & 0xFF; diff --git a/AltairZ80/altairZ80_cpu.c b/AltairZ80/altairZ80_cpu.c index 5fe951ee..3ec06947 100644 --- a/AltairZ80/altairZ80_cpu.c +++ b/AltairZ80/altairZ80_cpu.c @@ -1,30 +1,30 @@ -/* altairz80_cpu.c: MITS Altair CPU (8080 and Z80) +/* altairz80_cpu.c: MITS Altair CPU (8080 and Z80) - Copyright (c) 2002-2005, Peter Schorn + Copyright (c) 2002-2005, 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: + 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 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. + 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. + 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) + 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" @@ -33,111 +33,111 @@ #include #endif -#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 +#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 */ +#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 */ -#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 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 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 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 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 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 - In case a Z80 instruction is executed on an 8080 the following two cases exist: - 1) Trapping is enabled: execution stops - 2) Trapping is not enabled: decoding continues with the next byte -*/ -#define checkCPU8080 \ - if ((cpu_unit.flags & UNIT_CHIP) == 0) { \ - if (cpu_unit.flags & UNIT_OPSTOP) { \ - reason = STOP_OPCODE; \ - goto end_decode; \ - } \ - else { \ - sim_brk_pend = FALSE; \ - continue; \ - } \ - } +/* checkCPU8080 must be invoked whenever a Z80 only instruction is executed + In case a Z80 instruction is executed on an 8080 the following two cases exist: + 1) Trapping is enabled: execution stops + 2) Trapping is not enabled: decoding continues with the next byte +*/ +#define checkCPU8080 \ + if ((cpu_unit.flags & UNIT_CHIP) == 0) { \ + if (cpu_unit.flags & UNIT_OPSTOP) { \ + reason = STOP_OPCODE; \ + goto end_decode; \ + } \ + else { \ + sim_brk_pend = FALSE; \ + continue; \ + } \ + } /* 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 checkCPUZ80 \ + if (cpu_unit.flags & UNIT_OPSTOP) { \ + reason = STOP_OPCODE; \ + goto end_decode; \ + } -#define POP(x) { \ - register uint32 y = RAM_pp(SP); \ - x = y + (RAM_pp(SP) << 8); \ +#define POP(x) { \ + register uint32 y = RAM_pp(SP); \ + x = y + (RAM_pp(SP) << 8); \ } -#define JPC(cond) { \ - tStates += 10; \ - if (cond) { \ - PCQ_ENTRY(PC - 1); \ - PC = GetWORD(PC); \ - } \ - else { \ - PC += 2; \ - } \ +#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; \ - } \ +#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 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 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 char messageBuffer[]; extern void printMessage(void); @@ -163,13 +163,13 @@ uint32 getCommon(void); void setCommon(uint32 c); static void warnUnsuccessfulWriteAttempt(const uint32 Addr); static uint8 warnUnsuccessfulReadAttempt(const uint32 Addr); -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_banked (UNIT *uptr, int32 value, char *cptr, void *desc); -static t_stat cpu_set_nonbanked (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_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_banked (UNIT *uptr, int32 value, char *cptr, void *desc); +static t_stat cpu_set_nonbanked (UNIT *uptr, int32 value, char *cptr, void *desc); +static t_stat cpu_set_size (UNIT *uptr, int32 value, char *cptr, void *desc); static void prepareMemoryAccessMessage(t_addr loc); static void checkROMBoundaries(void); static void reset_memory(void); @@ -182,997 +182,1004 @@ static void PutWORD(register uint32 a, register uint32 v); static t_bool sim_brk_lookup (const t_addr bloc, const int32 btyp); static void resetCell(const int32 address, const int32 bank); -/* CPU data structures - cpu_dev CPU device descriptor - cpu_unit CPU unit descriptor - cpu_reg CPU register list - cpu_mod CPU modifiers list +/* 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) }; +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 */ -static int32 bankSelect = 0; /* determines selected memory bank */ -static 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 milliseconds */ -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 */ + 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 */ +static int32 bankSelect = 0; /* determines selected memory bank */ +static 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 milliseconds */ +static uint32 executedTStates = 0; /* executed t-states */ +static uint16 pcq[PCQ_SIZE] = { /* PC queue */ + 0 +}; +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 } }; + { 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 } }; + { 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, 0, - NULL, NULL, NULL }; + "CPU", &cpu_unit, cpu_reg, cpu_mod, + 1, 16, 16, 1, 16, 8, + &cpu_ex, &cpu_dep, &cpu_reset, + NULL, NULL, NULL, + NULL, 0, 0, + NULL, NULL, NULL +}; /* data structure for IN/OUT instructions */ struct idev { - int32 (*routine)(const int32, const int32, const int32); + 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 +/* 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 */ + {&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); + dev_table[Port].routine(Port, 1, Value); } static INLINE uint32 in(const uint32 Port) { - return dev_table[Port].routine(Port, 0, 0); + 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] 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, + 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 + 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, + 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, + 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 */ + (((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, + 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, + 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, + 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, + 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, + 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, + 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, + 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, + 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, + 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, + 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 */ + (((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, + 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 */ + (((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, + 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, + 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 */ + ((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, + 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, + 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 */ + (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, + 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, + 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, + 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, + 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 @@ -1182,4477 +1189,5064 @@ 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"); - } - } + 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"); - } - } + 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"); - } - } + 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"); - } - } + 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"); - } - } + 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"); - } - } + 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"); - } - } + 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"); - } - } + 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"); - } - } + 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"); - } - } + 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"); - } - } + 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"); - } - } + 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"); - } - } + 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"); - } - } + 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"); - } - } + 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"); - } - } + 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"); - } - } + 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"); - } - } + 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"); - } - } + 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"); - } - } + 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"); - } - } + 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"); - } - } + 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"); - } - } + 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 } */ -/* Memory management */ +/* Memory management */ static int32 lowProtect; static int32 highProtect; static int32 isProtected = FALSE; void protect(const int32 l, const int32 h) { - isProtected = TRUE; - lowProtect = l; - highProtect = h; + isProtected = TRUE; + lowProtect = l; + highProtect = h; } -static uint8 M[MAXMEMSIZE][MAXBANKS]; /* RAM which is present */ +static uint8 M[MAXMEMSIZE][MAXBANKS]; /* RAM which is present */ static void warnUnsuccessfulWriteAttempt(const uint32 Addr) { - if (cpu_unit.flags & UNIT_WARNROM) { - if (addressIsInROM(Addr)) { - message2("Attempt to write to ROM " AddressFormat ".", Addr); - } - else { - message2("Attempt to write to non existing memory " AddressFormat ".", Addr); - } - } + if (cpu_unit.flags & UNIT_WARNROM) { + if (addressIsInROM(Addr)) { + message2("Attempt to write to ROM " AddressFormat ".", Addr); + } + else { + message2("Attempt to write to non existing memory " AddressFormat ".", Addr); + } + } } static uint8 warnUnsuccessfulReadAttempt(const uint32 Addr) { - if (cpu_unit.flags & UNIT_WARNROM) { - message2("Attempt to read from non existing memory " AddressFormat ".", Addr); - } - return 0xff; + if (cpu_unit.flags & UNIT_WARNROM) { + message2("Attempt to read from non existing memory " AddressFormat ".", 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))); + 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) ); + 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) ); } static 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); - } + 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); + } } static 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); - } - } + 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); + } + } } 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); - } - } + 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); + } + } } 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; - } + 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; + } } void PutBYTEBasic(const uint32 Addr, const uint32 Bank, const uint32 Value) { - M[Addr & ADDRMASK][Bank & BANKMASK] = Value; + M[Addr & ADDRMASK][Bank & BANKMASK] = Value; } int32 install_bootrom(void) { - extern int32 bootrom[bootrom_size]; - 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; + extern int32 bootrom[bootrom_size]; + 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 void resetCell(const int32 address, const int32 bank) { - if (!(isProtected && (bank == 0) && (lowProtect <= address) && (address <= highProtect))) { - M[address][bank] = 0; - } + if (!(isProtected && (bank == 0) && (lowProtect <= address) && (address <= highProtect))) { + M[address][bank] = 0; + } } /* 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; + *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; + M[addr & ADDRMASK][(addr >> 16) & BANKMASK] = val & 0xff; + return SCPE_OK; } int32 getBankSelect(void) { - return bankSelect; + return bankSelect; } void setBankSelect(int32 b) { - bankSelect = b; + bankSelect = b; } uint32 getCommon(void) { - return common; + return common; } void setCommon(uint32 c) { - common = c; + common = c; } uint8 GetBYTEWrapper(register uint32 Addr) { /* make sure that non-inlined version exists */ - return GetBYTE(Addr); + return GetBYTE(Addr); } void PutBYTEWrapper(register uint32 Addr, register uint32 Value) { - PutBYTE(Addr, Value); + PutBYTE(Addr, Value); } -#define RAM_mm(a) GetBYTE(a--) -#define RAM_pp(a) GetBYTE(a++) +#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) +#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); +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 + 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; + 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) { - extern char memoryAccessMessage[]; - sprintf(memoryAccessMessage, "Memory access breakpoint [%04xh]", loc); + extern char memoryAccessMessage[]; + sprintf(memoryAccessMessage, "Memory access breakpoint [%04xh]", loc); } -#define PUSH(x) { \ - mm_PutBYTE(SP, (x) >> 8); \ - mm_PutBYTE(SP, x); \ +#define PUSH(x) { \ + mm_PutBYTE(SP, (x) >> 8); \ + mm_PutBYTE(SP, x); \ } -#define CheckBreakByte(a) \ - if (sim_brk_summ && sim_brk_test(a, SWMASK('M'))) { \ - reason = STOP_MEM; \ - prepareMemoryAccessMessage(a); \ - goto end_decode; \ - } +#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 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)) t_stat 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; - extern int32 sim_brk_summ; - 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 = 0; - register uint32 acu = 0; - register uint32 sum; - register uint32 cbits; - register uint32 op; - register uint32 adr; - /* tStates contains the number of t-states executed. One t-state is executed - in one microsecond on a 1MHz CPU. tStates is used for real-time simulations. */ - register uint32 tStates; - uint32 tStatesInSlice; /* number of t-states in 10 mSec time-slice */ - uint32 startTime; - int32 br1, br2, tStateModifier = FALSE; + 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; + extern int32 sim_brk_summ; + 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 = 0; + register uint32 acu = 0; + register uint32 sum; + register uint32 cbits; + register uint32 op; + register uint32 adr; + /* tStates contains the number of t-states executed. One t-state is executed + in one microsecond on a 1MHz CPU. tStates is used for real-time simulations. */ + register uint32 tStates; + uint32 tStatesInSlice; /* number of t-states in 10 mSec time-slice */ + uint32 startTime; + int32 br1, br2, tStateModifier = FALSE; - AF = AF_S; - BC = BC_S; - DE = DE_S; - HL = HL_S; - PC = saved_PC & ADDRMASK; - SP = SP_S; - IX = IX_S; - IY = IY_S; - 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; - } + AF = AF_S; + BC = BC_S; + DE = DE_S; + HL = HL_S; + PC = saved_PC & ADDRMASK; + SP = SP_S; + IX = IX_S; + IY = IY_S; + 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; - } - } + /* 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; + if (specialProcessing) { /* quick check for special processing */ + if (clockFrequency && (tStates >= tStatesInSlice)) { + /* clockFrequency != 0 implies that real time clock is available */ + startTime += sliceLength; + tStates -= tStatesInSlice; #if defined (_WIN32) - while (sim_os_msec() <= startTime) {} /* poor man's sleep */ + while (sim_os_msec() <= startTime) {} /* poor man's sleep */ #else - { - uint32 now; - if (startTime > (now = sim_os_msec())) { - usleep(1000 * (startTime - now)); - } - } + { + uint32 now; + if (startTime > (now = sim_os_msec())) { + usleep(1000 * (startTime - now)); + } + } #endif - } + } - if (timerInterrupt && (IFF_S & 1)) { - timerInterrupt = FALSE; - specialProcessing = clockFrequency | sim_brk_summ; - IFF_S = 0; /* disable interrupts */ - CheckBreakTwoBytesExtended(SP - 2, SP - 1, (timerInterrupt = TRUE, IFF_S |= 1)); - PUSH(PC); - PCQ_ENTRY(PC - 1); - PC = timerInterruptHandler & ADDRMASK; - } + if (timerInterrupt && (IFF_S & 1)) { + timerInterrupt = FALSE; + specialProcessing = clockFrequency | sim_brk_summ; + IFF_S = 0; /* disable interrupts */ + CheckBreakTwoBytesExtended(SP - 2, SP - 1, (timerInterrupt = TRUE, IFF_S |= 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; - } - } + if (sim_brk_summ && (sim_brk_lookup(PC, SWMASK('E')) == TRUE)) { /* breakpoint? */ + reason = STOP_IBKPT; /* stop simulation */ + break; + } + } - PCX = PC; - sim_interval--; + 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); /* SetPV2 uses temp */ - break; - case 0x05: /* DEC B */ - tStates += 4; - sim_brk_pend = FALSE; - BC -= 0x100; - temp = hreg(BC); - AF = (AF & ~0xfe) | decTable[temp] | SetPV2(0x7f); /* SetPV2 uses temp */ - 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; - temp = AF; - AF = AF1_S; - AF1_S = temp; - 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 += (int8) 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); /* SetPV2 uses temp */ - break; - case 0x15: /* DEC D */ - tStates += 4; - sim_brk_pend = FALSE; - DE -= 0x100; - temp = hreg(DE); - AF = (AF & ~0xfe) | decTable[temp] | SetPV2(0x7f); /* SetPV2 uses temp */ - 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 += (int8) 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 += (int8) 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); /* SetPV2 uses temp */ - break; - case 0x25: /* DEC H */ - tStates += 4; - sim_brk_pend = FALSE; - HL -= 0x100; - temp = hreg(HL); - AF = (AF & ~0xfe) | decTable[temp] | SetPV2(0x7f); /* SetPV2 uses temp */ - 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 += (int8) 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 += (int8) 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 += (int8) 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); /* SetPV2 uses temp */ - break; - case 0x3d: /* DEC A */ - tStates += 4; - sim_brk_pend = FALSE; - AF -= 0x100; - temp = hreg(AF); - AF = (AF & ~0xfe) | decTable[temp] | SetPV2(0x7f); /* SetPV2 uses temp */ - 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; - temp = BC; - BC = BC1_S; - BC1_S = temp; - temp = DE; - DE = DE1_S; - DE1_S = temp; - temp = HL; - HL = HL1_S; - HL1_S = temp; - 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 + (int8) 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 + (int8) 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 + (int8) 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 + (int8) 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 + (int8) 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 + (int8) 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 + (int8) 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 + (int8) 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 + (int8) 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 + (int8) RAM_pp(PC); - CheckBreakByte(adr); - PutBYTE(adr, hreg(BC)); - break; - case 0x71: /* LD (IX+dd),C */ - tStates += 19; - adr = IX + (int8) RAM_pp(PC); - CheckBreakByte(adr); - PutBYTE(adr, lreg(BC)); - break; - case 0x72: /* LD (IX+dd),D */ - tStates += 19; - adr = IX + (int8) RAM_pp(PC); - CheckBreakByte(adr); - PutBYTE(adr, hreg(DE)); - break; - case 0x73: /* LD (IX+dd),E */ - tStates += 19; - adr = IX + (int8) RAM_pp(PC); - CheckBreakByte(adr); - PutBYTE(adr, lreg(DE)); - break; - case 0x74: /* LD (IX+dd),H */ - tStates += 19; - adr = IX + (int8) RAM_pp(PC); - CheckBreakByte(adr); - PutBYTE(adr, hreg(HL)); - break; - case 0x75: /* LD (IX+dd),L */ - tStates += 19; - adr = IX + (int8) RAM_pp(PC); - CheckBreakByte(adr); - PutBYTE(adr, lreg(HL)); - break; - case 0x77: /* LD (IX+dd),A */ - tStates += 19; - adr = IX + (int8) 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 + (int8) 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 + (int8) 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 + (int8) 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 + (int8) 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 + (int8) 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 + (int8) 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 + (int8) 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 + (int8) 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 + (int8) 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 + (int8) 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_S |= IFF_S >> 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_S = (IR_S & 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_S |= IFF_S >> 1; - CheckBreakWord(SP); - PCQ_ENTRY(PC - 2); - POP(PC); - break; - case 0x4f: /* LD R,A */ - tStates += 9; - sim_brk_pend = FALSE; - IR_S = (IR_S & ~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_S & ~0xff) | ((IR_S >> 8) & 0x80) | (((IR_S & ~0xff) == 0) << 6) | ((IFF_S & 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_S & 0xff) << 8) | (IR_S & 0x80) | - (((IR_S & 0xff) == 0) << 6) | ((IFF_S & 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_S = 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_S = 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 + (int8) 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 + (int8) 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 + (int8) 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 + (int8) 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 + (int8) 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 + (int8) 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 + (int8) 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 + (int8) 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 + (int8) 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 + (int8) RAM_pp(PC); - CheckBreakByte(adr); - PutBYTE(adr, hreg(BC)); - break; - case 0x71: /* LD (IY+dd),C */ - tStates += 19; - adr = IY + (int8) RAM_pp(PC); - CheckBreakByte(adr); - PutBYTE(adr, lreg(BC)); - break; - case 0x72: /* LD (IY+dd),D */ - tStates += 19; - adr = IY + (int8) RAM_pp(PC); - CheckBreakByte(adr); - PutBYTE(adr, hreg(DE)); - break; - case 0x73: /* LD (IY+dd),E */ - tStates += 19; - adr = IY + (int8) RAM_pp(PC); - CheckBreakByte(adr); - PutBYTE(adr, lreg(DE)); - break; - case 0x74: /* LD (IY+dd),H */ - tStates += 19; - adr = IY + (int8) RAM_pp(PC); - CheckBreakByte(adr); - PutBYTE(adr, hreg(HL)); - break; - case 0x75: /* LD (IY+dd),L */ - tStates += 19; - adr = IY + (int8) RAM_pp(PC); - CheckBreakByte(adr); - PutBYTE(adr, lreg(HL)); - break; - case 0x77: /* LD (IY+dd),A */ - tStates += 19; - adr = IY + (int8) 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 + (int8) 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 + (int8) 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 + (int8) 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 + (int8) 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 + (int8) 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 + (int8) 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 + (int8) 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 + (int8) 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 + (int8) 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 + (int8) 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: + /* 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)) { - /* simulation halted */ - saved_PC = ((reason == STOP_OPCODE) || (reason == STOP_MEM)) ? PCX : PC; - pcq_r -> qptr = pcq_p; /* update pc q ptr */ - AF_S = AF; - BC_S = BC; - DE_S = DE; - HL_S = HL; - IX_S = IX; - IY_S = IY; - SP_S = SP; - executedTStates = tStates; - return reason; + 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); /* SetPV2 uses temp */ + break; + + case 0x05: /* DEC B */ + tStates += 4; + sim_brk_pend = FALSE; + BC -= 0x100; + temp = hreg(BC); + AF = (AF & ~0xfe) | decTable[temp] | SetPV2(0x7f); /* SetPV2 uses temp */ + 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; + temp = AF; + AF = AF1_S; + AF1_S = temp; + 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 += (int8) 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); /* SetPV2 uses temp */ + break; + + case 0x15: /* DEC D */ + tStates += 4; + sim_brk_pend = FALSE; + DE -= 0x100; + temp = hreg(DE); + AF = (AF & ~0xfe) | decTable[temp] | SetPV2(0x7f); /* SetPV2 uses temp */ + 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 += (int8) 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 += (int8) 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); /* SetPV2 uses temp */ + break; + + case 0x25: /* DEC H */ + tStates += 4; + sim_brk_pend = FALSE; + HL -= 0x100; + temp = hreg(HL); + AF = (AF & ~0xfe) | decTable[temp] | SetPV2(0x7f); /* SetPV2 uses temp */ + 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 += (int8) 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 += (int8) 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 += (int8) 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); /* SetPV2 uses temp */ + break; + + case 0x3d: /* DEC A */ + tStates += 4; + sim_brk_pend = FALSE; + AF -= 0x100; + temp = hreg(AF); + AF = (AF & ~0xfe) | decTable[temp] | SetPV2(0x7f); /* SetPV2 uses temp */ + 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; + temp = BC; + BC = BC1_S; + BC1_S = temp; + temp = DE; + DE = DE1_S; + DE1_S = temp; + temp = HL; + HL = HL1_S; + HL1_S = temp; + 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 + (int8) 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 + (int8) 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 + (int8) 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 + (int8) 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 + (int8) 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 + (int8) 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 + (int8) 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 + (int8) 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 + (int8) 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 + (int8) RAM_pp(PC); + CheckBreakByte(adr); + PutBYTE(adr, hreg(BC)); + break; + + case 0x71: /* LD (IX+dd),C */ + tStates += 19; + adr = IX + (int8) RAM_pp(PC); + CheckBreakByte(adr); + PutBYTE(adr, lreg(BC)); + break; + + case 0x72: /* LD (IX+dd),D */ + tStates += 19; + adr = IX + (int8) RAM_pp(PC); + CheckBreakByte(adr); + PutBYTE(adr, hreg(DE)); + break; + + case 0x73: /* LD (IX+dd),E */ + tStates += 19; + adr = IX + (int8) RAM_pp(PC); + CheckBreakByte(adr); + PutBYTE(adr, lreg(DE)); + break; + + case 0x74: /* LD (IX+dd),H */ + tStates += 19; + adr = IX + (int8) RAM_pp(PC); + CheckBreakByte(adr); + PutBYTE(adr, hreg(HL)); + break; + + case 0x75: /* LD (IX+dd),L */ + tStates += 19; + adr = IX + (int8) RAM_pp(PC); + CheckBreakByte(adr); + PutBYTE(adr, lreg(HL)); + break; + + case 0x77: /* LD (IX+dd),A */ + tStates += 19; + adr = IX + (int8) 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 + (int8) 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 + (int8) 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 + (int8) 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 + (int8) 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 + (int8) 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 + (int8) 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 + (int8) 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 + (int8) 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 + (int8) 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 + (int8) 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_S |= IFF_S >> 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_S = (IR_S & 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_S |= IFF_S >> 1; + CheckBreakWord(SP); + PCQ_ENTRY(PC - 2); + POP(PC); + break; + + case 0x4f: /* LD R,A */ + tStates += 9; + sim_brk_pend = FALSE; + IR_S = (IR_S & ~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_S & ~0xff) | ((IR_S >> 8) & 0x80) | (((IR_S & ~0xff) == 0) << 6) | ((IFF_S & 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_S & 0xff) << 8) | (IR_S & 0x80) | + (((IR_S & 0xff) == 0) << 6) | ((IFF_S & 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_S = 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_S = 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 + (int8) 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 + (int8) 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 + (int8) 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 + (int8) 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 + (int8) 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 + (int8) 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 + (int8) 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 + (int8) 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 + (int8) 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 + (int8) RAM_pp(PC); + CheckBreakByte(adr); + PutBYTE(adr, hreg(BC)); + break; + + case 0x71: /* LD (IY+dd),C */ + tStates += 19; + adr = IY + (int8) RAM_pp(PC); + CheckBreakByte(adr); + PutBYTE(adr, lreg(BC)); + break; + + case 0x72: /* LD (IY+dd),D */ + tStates += 19; + adr = IY + (int8) RAM_pp(PC); + CheckBreakByte(adr); + PutBYTE(adr, hreg(DE)); + break; + + case 0x73: /* LD (IY+dd),E */ + tStates += 19; + adr = IY + (int8) RAM_pp(PC); + CheckBreakByte(adr); + PutBYTE(adr, lreg(DE)); + break; + + case 0x74: /* LD (IY+dd),H */ + tStates += 19; + adr = IY + (int8) RAM_pp(PC); + CheckBreakByte(adr); + PutBYTE(adr, hreg(HL)); + break; + + case 0x75: /* LD (IY+dd),L */ + tStates += 19; + adr = IY + (int8) RAM_pp(PC); + CheckBreakByte(adr); + PutBYTE(adr, lreg(HL)); + break; + + case 0x77: /* LD (IY+dd),A */ + tStates += 19; + adr = IY + (int8) 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 + (int8) 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 + (int8) 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 + (int8) 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 + (int8) 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 + (int8) 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 + (int8) 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 + (int8) 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 + (int8) 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 + (int8) 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 + (int8) 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: + + /* simulation halted */ + saved_PC = ((reason == STOP_OPCODE) || (reason == STOP_MEM)) ? PCX : PC; + pcq_r -> qptr = pcq_p; /* update pc q ptr */ + AF_S = AF; + BC_S = BC; + DE_S = DE; + HL_S = HL; + IX_S = IX; + IY_S = IY; + SP_S = SP; + executedTStates = tStates; + return reason; } 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; + 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); - } + if (cntROM) { + printf("Warning: %d bytes written to ROM [%04X - %04X].\n", cntROM, ROMLow, ROMHigh); + } } /* reset routine */ t_stat cpu_reset(DEVICE *dptr) { - extern int32 sim_brk_types, sim_brk_dflt; /* breakpoint info */ - int32 i; - AF_S = AF1_S = 0; - BC_S = DE_S = HL_S = 0; - BC1_S = DE1_S = HL1_S = 0; - IR_S = IX_S = IY_S = SP_S = 0; - IFF_S = 3; - setBankSelect(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; + extern int32 sim_brk_types, sim_brk_dflt; /* breakpoint info */ + int32 i; + AF_S = AF1_S = 0; + BC_S = DE_S = HL_S = 0; + BC1_S = DE1_S = HL1_S = 0; + IR_S = IX_S = IY_S = SP_S = 0; + IFF_S = 3; + setBankSelect(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; } 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; - } - } + 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; + } + } } -#if !defined(ALTAIROPT) static t_stat cpu_set_rom(UNIT *uptr, int32 value, char *cptr, void *desc) { - checkROMBoundaries(); - return SCPE_OK; + 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; + 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; + 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; + 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; + 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; + if (MEMSIZE == (MAXBANKS * MAXMEMSIZE)) { + MEMSIZE = previousCapacity ? previousCapacity : 64*KB; + } + cpu_dev.awidth = 16; + return SCPE_OK; } -#endif 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; + 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; } -/* 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. +/* 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. */ t_stat 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(NULL, cptr, &lo, &hi, 16, ADDRMASK, 0); - if (result == NULL) { - return SCPE_ARG; - } - for (j = lo; j <= hi; j++) { - if (putc(GetBYTE(j), fileref) == EOF) { - return SCPE_IOERR; - } - } - printf("%d byte%s dumped [%x - %x].\n", hi + 1 - lo, hi == lo ? "" : "s", 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; + 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(NULL, cptr, &lo, &hi, 16, ADDRMASK, 0); + if (result == NULL) { + return SCPE_ARG; + } + for (j = lo; j <= hi; j++) { + if (putc(GetBYTE(j), fileref) == EOF) { + return SCPE_IOERR; + } + } + printf("%d byte%s dumped [%x - %x].\n", hi + 1 - lo, hi == lo ? "" : "s", 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_defs.h b/AltairZ80/altairZ80_defs.h index 9e2574ed..e3c58970 100644 --- a/AltairZ80/altairZ80_defs.h +++ b/AltairZ80/altairZ80_defs.h @@ -1,80 +1,80 @@ -/* altairz80_defs.h: MITS Altair simulator definitions +/* altairz80_defs.h: MITS Altair simulator definitions - Copyright (c) 2002-2005, Peter Schorn + Copyright (c) 2002-2005, 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: + 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 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. + 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. + 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 + Based on work by Charles E Owen (c) 1997 */ -#include "sim_defs.h" /* simulator definitions */ +#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 address of ROM */ -#define defaultROMHigh 0xffff /* default for highest address of ROM */ +#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 address of ROM */ +#define defaultROMHigh 0xffff /* default for highest address 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 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 invalid 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 UNIT_V_OPSTOP (UNIT_V_UF+0) /* stop on invalid 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() +#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". */ +/* The default is to use "inline". */ #if defined(NO_INLINE) #define INLINE #else diff --git a/AltairZ80/altairZ80_dsk.c b/AltairZ80/altairZ80_dsk.c index 20dba70c..f5ae4409 100644 --- a/AltairZ80/altairZ80_dsk.c +++ b/AltairZ80/altairZ80_dsk.c @@ -1,130 +1,130 @@ -/* altairz80_dsk.c: MITS Altair 88-DISK Simulator +/* altairz80_dsk.c: MITS Altair 88-DISK Simulator - Copyright (c) 2002-2005, Peter Schorn + Copyright (c) 2002-2005, 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: + 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 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. + 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. + 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 + 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 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 addresses, - standardly, these are device numbers 10, 11, and 12 (octal). + The controller is interfaced to the CPU by use of 3 I/O addresses, + standardly, these are device numbers 10, 11, and 12 (octal). - Address Mode Function - ------- ---- -------- + 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 + 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): + Drive Select Out (Device 10 OUT): - +---+---+---+---+---+---+---+---+ - | C | X | X | X | Device | - +---+---+---+---+---+---+---+---+ + +---+---+---+---+---+---+---+---+ + | 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. + 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): + Drive Status In (Device 10 IN): - +---+---+---+---+---+---+---+---+ - | R | Z | I | X | X | H | M | W | - +---+---+---+---+---+---+---+---+ + +---+---+---+---+---+---+---+---+ + | 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 + 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): + Drive Control (Device 11 OUT): - +---+---+---+---+---+---+---+---+ - | W | C | D | E | U | H | O | I | - +---+---+---+---+---+---+---+---+ + +---+---+---+---+---+---+---+---+ + | 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. + 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): + 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. + 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 | 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. + 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) +#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); @@ -149,140 +149,144 @@ 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 */ +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 */ + 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) } }; + { 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 } }; + { 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 } }; + { 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, 0, - NULL, NULL, NULL }; + "DSK", dsk_unit, dsk_reg, dsk_mod, + 8, 10, 31, 1, 8, 8, + NULL, NULL, &dsk_reset, + &dsk_boot, NULL, NULL, + NULL, 0, 0, + NULL, 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; + 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; + 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; + 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"; + return io == 0 ? "IN" : "OUT"; } /* service routines to handle simulator functions */ @@ -290,281 +294,280 @@ static char* selectInOut(const int32 io) { /* service routine - actually gets char & places in buffer */ static t_stat dsk_svc(UNIT *uptr) { - return SCPE_OK; + 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; + 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. +/* 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; + 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. +/* 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. + 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. +/* 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."); - } - return 0xff; /* no drive selected - can do nothing */ - } - return (~current_flag[current_disk]) & 0xff; /* return the COMPLEMENT! */ - } + 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."); + } + 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", 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]++; + /* 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", 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.", 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 */ + } + 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.", selectInOut(io)); - } - return 0; /* no drive selected - can do nothing */ - } + if (current_disk >= NUM_OF_DSK) { + if (hasVerbose() && (warnDSK11 < warnLevelDSK)) { + warnDSK11++; +/*03*/ message2("Attempt of %s 0x09 on unattached disk - ignored.", 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.", current_disk); - } - if (trace_flag & TRACE_IN_OUT) { - message1("IN 0x09"); - } - 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 */ - } - } + /* 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.", current_disk); + } + if (trace_flag & TRACE_IN_OUT) { + message1("IN 0x09"); + } + 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 */ + in9_count = 0; + /* drive functions */ - if (trace_flag & TRACE_IN_OUT) { - message2("OUT 0x09: %x", 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", 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 (trace_flag & TRACE_IN_OUT) { + message2("OUT 0x09: %x", 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", 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", 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 (data & 0x02) { /* step head out */ + if (trace_flag & TRACE_TRACK_STUCK) { + if (current_track[current_disk] == 0) { + message2("Unnecessary step out for disk %d", 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 (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 & 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; - } + 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 */ + /* 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 */ + 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); + 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; + 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.", selectInOut(io)); - } - return 0; - } + if (current_disk >= NUM_OF_DSK) { + if (hasVerbose() && (warnDSK12 < warnLevelDSK)) { + warnDSK12++; +/*04*/ message2("Attempt of %s 0x0a on unattached disk - ignored.", 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", 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 */ - } + /* 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", 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", current_disk, current_track[current_disk], current_sector[current_disk]); - } - if (dskseek(uptr)) { - message4("fseek failed D%d T%d S%d", 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", 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.", current_disk); - } - current_flag[current_disk] &= 0xfe; /* ENWD off */ - current_byte[current_disk] = 0xff; - dirty = FALSE; + 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", current_disk, current_track[current_disk], current_sector[current_disk]); + } + if (dskseek(uptr)) { + message4("fseek failed D%d T%d S%d", 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", 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.", 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 index 34ac09e9..6967c518 100644 --- a/AltairZ80/altairZ80_sio.c +++ b/AltairZ80/altairZ80_sio.c @@ -1,52 +1,52 @@ -/* altairz80_sio: MITS Altair serial I/O card +/* altairz80_sio: MITS Altair serial I/O card - Copyright (c) 2002-2005, Peter Schorn + Copyright (c) 2002-2005, 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: + 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 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. + 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. + 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 + 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. + 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: + 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 | - +---+---+---+---+---+---+---+---+ + +---+---+---+---+---+---+---+---+ + | 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. + 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. + A read to the data port gets the buffered character, a write + to the data port writes the character to the device. */ #include @@ -56,45 +56,45 @@ #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) /* upper 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_MAP (UNIT_V_UF + 4) /* mapping mode on */ -#define UNIT_MAP (1 << UNIT_V_MAP) +#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) /* upper 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_MAP (UNIT_V_UF + 4) /* mapping mode on */ +#define UNIT_MAP (1 << UNIT_V_MAP) -#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 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 Terminals 4 /* lines per mux */ -#define BACKSPACE_CHAR 0x08 /* backspace character */ -#define DELETE_CHAR 0x7f /* delete character */ -#define CONTROLZ_CHAR 0x1a /* control Z character */ +#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_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); +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); @@ -127,241 +127,259 @@ extern int32 SR; 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 */ +/* 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 */ +/* 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 */ +/* 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 */ +/* 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 */ +/* 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 and attempt to perform IN or OUT on an unassigned PORT */ +/* 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 and attempt 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 */ + 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, TerminalLines}; /* mux descriptor */ +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] = { /* four terminals */ + {0} +}; +static TMXR altairTMXR = { /* mux descriptor */ + Terminals, 0, 0, TerminalLines +}; static UNIT sio_unit = { UDATA (&sio_svc, UNIT_ATTABLE + UNIT_MAP, 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 } }; + { 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 */ - { UNIT_MAP, 0, "NOMAP", "NOMAP", NULL }, /* disable character mapping */ - { UNIT_MAP, UNIT_MAP, "MAP", "MAP", NULL }, /* enable all character mapping */ - { 0 } }; + { 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 */ + { UNIT_MAP, 0, "NOMAP", "NOMAP", NULL }, /* disable character mapping */ + { UNIT_MAP, UNIT_MAP, "MAP", "MAP", NULL }, /* enable all character mapping */ + { 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, 0, - NULL, NULL, NULL }; + "SIO", &sio_unit, sio_reg, sio_mod, + 1, 10, 31, 1, 8, 8, + NULL, NULL, &sio_reset, + NULL, &sio_attach, &sio_detach, + NULL, 0, 0, + NULL, NULL, NULL }; -static UNIT ptr_unit = { UDATA (NULL, UNIT_SEQ + UNIT_ATTABLE + UNIT_ROABLE, 0), - KBD_POLL_WAIT }; +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 } }; + { 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, 0, - NULL, NULL, NULL }; + "PTR", &ptr_unit, ptr_reg, NULL, + 1, 10, 31, 1, 8, 8, + NULL, NULL, &ptr_reset, + NULL, NULL, NULL, + NULL, 0, 0, + NULL, NULL, NULL +}; -static UNIT ptp_unit = { UDATA (NULL, UNIT_SEQ + UNIT_ATTABLE, 0), - KBD_POLL_WAIT }; +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 } }; + { 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, 0, - NULL, NULL, NULL }; + "PTP", &ptp_unit, ptp_reg, NULL, + 1, 10, 31, 1, 8, 8, + NULL, NULL, &ptp_reset, + NULL, NULL, NULL, + NULL, 0, 0, + NULL, 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 }; +/* 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 } }; + { 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 } }; + /* 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, 0, - NULL, NULL, NULL }; + "SIMH", &simh_unit, simh_reg, simh_mod, + 1, 10, 31, 1, 16, 4, + NULL, NULL, &simh_dev_reset, + NULL, NULL, NULL, + NULL, 0, 0, + NULL, NULL, NULL +}; char messageBuffer[256]; void printMessage(void) { - printf(messageBuffer); + printf(messageBuffer); #if defined(__NetBSD__) || defined (__OpenBSD__) || defined (__FreeBSD__) || defined (__APPLE__) /* need to make sure that carriage return is executed - ttrunstate() of scp_tty.c - has disabled \n translation */ - printf("\r\n"); + has disabled \n translation */ + printf("\r\n"); #else - printf("\n"); + printf("\n"); #endif - if (sim_log) { - fprintf(sim_log, messageBuffer); - fprintf(sim_log,"\n"); - } + if (sim_log) { + fprintf(sim_log, messageBuffer); + fprintf(sim_log,"\n"); + } } static void resetSIOWarningFlags(void) { - warnUnattachedPTP = 0; - warnUnattachedPTR = 0; - warnPTREOF = 0; - warnUnassignedPort = 0; + 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; + resetSIOWarningFlags(); + return SCPE_OK; } static t_stat sio_attach(UNIT *uptr, char *cptr) { - reset_sio_terminals(FALSE); - return tmxr_attach(&altairTMXR, uptr, cptr); /* attach mux */ + 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 */ - } + 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); + reset_sio_terminals(TRUE); + return tmxr_detach(&altairTMXR, uptr); } /* service routines to handle simulator functions */ @@ -369,757 +387,811 @@ static t_stat sio_detach(UNIT *uptr) { /* service routine - actually gets char & places in buffer */ static t_stat sio_svc(UNIT *uptr) { - int32 temp; + int32 temp; - sim_activate(&sio_unit, sio_unit.wait); /* continue poll */ + 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) { - TerminalLines[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; + 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) { + TerminalLines[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 (TerminalLines[i].conn > 0) { - tmxr_reset_ln(&TerminalLines[i]); - } - } - reset_sio_terminals(FALSE); - } - else { - reset_sio_terminals(TRUE); - } - sim_activate(&sio_unit, sio_unit.wait); /* activate unit */ - return SCPE_OK; + int32 i; + resetSIOWarningFlags(); + if (sio_unit.flags & UNIT_ATT) { + for (i = 0; i < Terminals; i++) { + if (TerminalLines[i].conn > 0) { + tmxr_reset_ln(&TerminalLines[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; + 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; + 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. +/* 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. + 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) + 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(&TerminalLines[ti]) > 0 ? 0x01 : 0) | - /* read possible if character available */ - ((TerminalLines[ti].conn) && (TerminalLines[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 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(&TerminalLines[ti]) > 0 ? 0x01 : 0) | + /* read possible if character available */ + ((TerminalLines[ti].conn) && (TerminalLines[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(&TerminalLines[ti]) & 0xff; - } - sio_terminals[ti].status &= 0xfe; - if (sio_unit.flags & UNIT_MAP) { - 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) && (sio_unit.flags & UNIT_MAP)) ? - 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(&TerminalLines[ti], d); /* status ignored */ - } - else { - sim_putchar(d); - } - return 0; /* ignored since OUT */ - } + 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(&TerminalLines[ti]) & 0xff; + } + sio_terminals[ti].status &= 0xfe; + if (sio_unit.flags & UNIT_MAP) { + 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) && (sio_unit.flags & UNIT_MAP)) ? + 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(&TerminalLines[ti], d); /* status ignored */ + } + 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."); - } - 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 */ - } + 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."); + } + 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."); - } - 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."); - } - 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.", data); - } - ptp_unit.pos++; - return 0; /* ignored since OUT */ - } + 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."); + } + 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."); + } + 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.", 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.", port); - } - else { - message3("Unassigned OUT(%2xh) -> %2xh - ignored.", port, data); - } - } - return io == 0 ? 0xff : 0; + if ((sio_unit.flags & UNIT_SIO_VERBOSE) && (warnUnassignedPort < warnLevelSIO)) { + warnUnassignedPort++; + if (io == 0) { + message2("Unassigned IN(%2xh) - ignored.", port); + } + else { + message3("Unassigned OUT(%2xh) -> %2xh - ignored.", port, data); + } + } + return io == 0 ? 0xff : 0; } int32 sr_dev(const int32 port, const int32 io, const int32 data) { - return io == 0 ? SR : 0; + return io == 0 ? SR : 0; } static int32 toBCD(const int32 x) { - return (x / 10) * 16 + (x % 10); + return (x / 10) * 16 + (x % 10); } static int32 fromBCD(const int32 x) { - return 10 * ((0xf0 & x) >> 4) + (0x0f & 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: +/* 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. + 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. + 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. + 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. + 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 */ +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 */ +#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; + 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"); - } + 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; - } + 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; + 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; + 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 command line 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 command line, 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).", cpmCommandLine, scp_error_messages[lastCPMStatus - SCPE_BASE]); - } + char cpmCommandLine[cpmCommandLineLength]; + uint32 i, len = (GetBYTEWrapper(0x80) & 0x7f) - 1; /* 0x80 contains length of command line, 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).", 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); + 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) +#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); + 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 */ + 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); + 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 = getBankSelect(); - } - 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 = getCommon() & 0xff; - getCommonPos = 1; - } - else { - result = (getCommon() >> 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.", - port); - } - result = lastCommand = 0; - } - return result; + 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 = getBankSelect(); + } + 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 = getCommon() & 0xff; + getCommonPos = 1; + } + else { + result = (getCommon() >> 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.", + 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) { - setBankSelect(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.", 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."); - } - } - 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.", delta); - } - else { - message1("No timer active."); - } - } - 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.", delta); - } - else { - message1("No timer active."); - } - } - 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.", - data, port); - } - } - } - return 0; /* ignored, since OUT */ + 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) { + setBankSelect(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.", 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."); + } + } + 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.", delta); + } + else { + message1("No timer active."); + } + } + 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.", delta); + } + else { + message1("No timer active."); + } + } + 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.", + 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); + return io == 0 ? simh_in(port) : simh_out(port, data); } diff --git a/AltairZ80/altairZ80_sys.c b/AltairZ80/altairZ80_sys.c index 26bcb9d2..7b8b4b35 100644 --- a/AltairZ80/altairZ80_sys.c +++ b/AltairZ80/altairZ80_sys.c @@ -1,30 +1,30 @@ -/* altairz80_sys.c: MITS Altair system interface +/* altairz80_sys.c: MITS Altair system interface - Copyright (c) 2002-2005, Peter Schorn + Copyright (c) 2002-2005, 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: + 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 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. + 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. + 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) + Based on work by Charles E Owen (c) 1997 + Disassembler from Marat Fayzullin ((c) 1995, 1996, 1997 - Commercial use prohibited) */ #include @@ -44,676 +44,694 @@ extern int32 saved_PC; 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); + 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); + 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 + 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 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" }; + "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 */ +/* 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 */ +/* 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 */ +/* 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 */ +/* 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 */ +/* 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 */ +/*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 +/* Symbolic disassembler - Inputs: - *val = instructions to disassemble - useZ80Mnemonics = > 0 iff Z80 mnemonics are to be used - addr = current PC - Outputs: - *S = output text + 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. + 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; + 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 (useZ80Mnemonics) { + switch(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; - } - } + case 0xcb: + B++; + T = MnemonicsCB[val[B++]]; + break; - 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); + 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 +/* Symbolic output - Inputs: - *of = output stream - addr = current PC - *val = pointer to values - *uptr = pointer to unit - sw = switches - Outputs: - status = error code + 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 */ + 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 */ } -/* checkbase determines the base of the number (ch, *numString) - and returns FALSE if the number is bad */ +/* checkbase 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); + 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); + 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 containing '_' 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); + int32 *at, int32 *hat, int32 *dollar) { + char pat = *pattern++; + char inp = *input++; + while ((pat) && (inp)) { + switch(pat) { + + case '_': /* patterns containing '_' 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' */ + 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; - } + 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++) { + 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 = -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++) { + 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; + 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 +/* 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 + 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); + 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); } diff --git a/AltairZ80/altairz80_hdsk.c b/AltairZ80/altairz80_hdsk.c index 7130c702..0da8a34b 100644 --- a/AltairZ80/altairz80_hdsk.c +++ b/AltairZ80/altairz80_hdsk.c @@ -1,49 +1,49 @@ -/* altairz80_hdsk.c: simulated hard disk device to increase capacity +/* altairz80_hdsk.c: simulated hard disk device to increase capacity - Copyright (c) 2002-2005, Peter Schorn + Copyright (c) 2002-2005, 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: + 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 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. + 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. + 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 +#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; @@ -70,8 +70,8 @@ static int32 doSeek(void); static int32 doRead(void); static int32 doWrite(void); -static int32 hdskLastCommand = hdsk_none; -static int32 hdskCommandPosition = 0; +static int32 hdskLastCommand = hdsk_none; +static int32 hdskCommandPosition = 0; static int32 selectedDisk; static int32 selectedSector; static int32 selectedTrack; @@ -79,310 +79,324 @@ 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) } }; + { 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 } }; + { 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 } }; + { 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, 0, - NULL, NULL, NULL }; + "HDSK", hdsk_unit, hdsk_reg, hdsk_mod, + 8, 10, 31, 1, 8, 8, + NULL, NULL, NULL, + &hdsk_boot, NULL, NULL, + NULL, 0, 0, + NULL, NULL, NULL +}; static t_stat hdsk_svc(UNIT *uptr) { - return SCPE_OK; + 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 */ + 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; + 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; + 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. +/* 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 + 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.", 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.", 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.", - 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.", - selectedDisk, selectedTrack, HDS_MAX_TRACKS); - } - selectedTrack = 0; - } - selectedDMA &= ADDRMASK; - if (hdskTrace) { - message6("%s HDSK%d Sector=%02d Track=%04d DMA=%04x", - (hdskLastCommand == hdsk_read) ? "Read" : "Write", - selectedDisk, selectedSector, selectedTrack, selectedDMA); - } - return TRUE; + int32 currentFlag; + if ((selectedDisk < 0) || (selectedDisk >= HDSK_NUMBER)) { + if (hdsk_hasVerbose()) { + message2("HDSK%d does not exist, will use HDSK0 instead.", 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.", 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.", + 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.", + selectedDisk, selectedTrack, HDS_MAX_TRACKS); + } + selectedTrack = 0; + } + selectedDMA &= ADDRMASK; + if (hdskTrace) { + message6("%s HDSK%d Sector=%02d Track=%04d DMA=%04x", + (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.", - selectedDisk, selectedSector, selectedTrack); - } - return CPM_ERROR; - } - else { - return CPM_OK; - } + 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.", + 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.", - 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; + 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.", + 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.", - 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.", - selectedDisk, selectedSector, selectedTrack); - } - return CPM_ERROR; - } - return CPM_OK; + 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.", + 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.", + 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).", - port, hdskLastCommand, hdskCommandPosition); - } - return CPM_OK; + 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).", + 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 */ + 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); + return io == 0 ? hdsk_in(port) : hdsk_out(data); } diff --git a/GRI/gri_cpu.c b/GRI/gri_cpu.c index cb814818..8c2f503f 100644 --- a/GRI/gri_cpu.c +++ b/GRI/gri_cpu.c @@ -1,6 +1,6 @@ /* gri_cpu.c: GRI-909 CPU simulator - Copyright (c) 2001-2004, Robert M. Supnik + Copyright (c) 2001-2005, 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"), @@ -19,98 +19,96 @@ 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 + 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 + cpu GRI-909 CPU - 18-Jul-04 RMS Fixed missing ao_update calls in AX, AY write - 17-Jul-04 RMS Revised MSR, EAO based on additional documentation - 14-Mar-03 RMS Fixed bug in SC queue tracking + 18-Jul-04 RMS Fixed missing ao_update calls in AX, AY write + 17-Jul-04 RMS Revised MSR, EAO based on additional documentation + 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 + 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 + | source | op | destination | move +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - <6:9> operation + <6:9> operation - xx1x complement - 01xx add 1 - 10xx rotate left 1 - 11xx rotate right 1 + 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: + + 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 + | 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 + | 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 + | source | op | mode| destination | memory ref +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | address or immediate | +-----------------------------------------------+ - <6:9> operation + <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 + 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 + | source | cond|rv|df| 0 0 0 0 1 1| cond jump +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | jump address | +-----------------------------------------------+ - <6:9> operation + <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. + 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. @@ -119,15 +117,15 @@ 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 + 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) + 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. @@ -139,51 +137,51 @@ 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 + 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) +#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 */ +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 */ +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); @@ -237,141 +235,146 @@ 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 */ + { &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 }; - + 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 + 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 } }; + { 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 } }; + { 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 }; - + "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; @@ -380,146 +383,174 @@ extern UNIT rtc_unit; /* Restore register state */ -SC = SC & AMASK; /* load local PC */ +SC = SC & AMASK; /* load local PC */ reason = 0; -ao_update (); /* update AO */ -sim_rtc_init (rtc_unit.wait); /* init calibration */ +ao_update (); /* update AO */ +sim_rtc_init (rtc_unit.wait); /* init calibration */ /* Main instruction fetch/decode loop */ -while (reason == 0) { /* loop until halted */ +while (reason == 0) { /* loop until halted */ -if (sim_interval <= 0) { /* check clock queue */ - if (reason = sim_process_event ()) break; } + 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 */ + 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; } + 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; } + 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; -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 */ + 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 */ + 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 (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_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 */ + } -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 */ - + else { /* memory reference */ + 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_update (); /* update AO */ -scq_r->qptr = scq_p; /* update sc q ptr */ +ao_update (); /* update AO */ +scq_r->qptr = scq_p; /* update sc q ptr */ return reason; } @@ -529,27 +560,32 @@ 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 */ +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 */ @@ -573,7 +609,7 @@ uint32 no_sf (uint32 fnc) { return (stop_opr << SF_V_REASON); } - + /* Zero device */ uint32 zero_rd (uint32 src) @@ -588,25 +624,30 @@ 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 */ +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? */ +if ((op & 010) || /* power always ok */ + ((op & 4) && (MSR & MSR_L)) || /* link set? */ + ((op & 2) && (MSR & MSR_BOV))) return 1; /* BOV set? */ return 0; } @@ -654,7 +695,7 @@ uint32 isr_sf (uint32 op) { return 0; } - + /* Memory address (05) */ uint32 ma_rd (uint32 src) @@ -706,11 +747,11 @@ return MSR & MSR_RW; t_stat msr_wr (uint32 src, uint32 dat) { -MSR = dat & MSR_RW; /* new MSR */ -ao_update (); /* update AOV */ +MSR = dat & MSR_RW; /* new MSR */ +ao_update (); /* update AOV */ return SCPE_OK; } - + /* Arithmetic operators (11:14) */ uint32 ao_update (void) @@ -718,22 +759,28 @@ uint32 ao_update (void) uint32 af = MSR_GET_FOA (MSR); switch (af) { -case AO_ADD: - AO = (AX + AY) & DMASK; /* add */ - break; -case AO_AND: - AO = AX & AY; /* and */ - break; -case AO_XOR: /* xor */ - AO = AX ^ AY; - break; -case AO_IOR: - AO = AX | AY; /* or */ - break; } -if ((AX + AY) & CBIT) MSR = MSR | MSR_AOV; /* always calc AOV */ + + case AO_ADD: + AO = (AX + AY) & DMASK; /* add */ + break; + + case AO_AND: + AO = AX & AY; /* and */ + break; + + case AO_XOR: /* xor */ + AO = AX ^ AY; + break; + + case AO_IOR: + AO = AX | AY; /* or */ + break; + } + +if ((AX + AY) & CBIT) MSR = MSR | MSR_AOV; /* always calc AOV */ else MSR = MSR & ~MSR_AOV; -if (SIGN & ((AX ^ (AX + AY)) & (~AX ^ AY))) /* always calc SOV */ - MSR = MSR | MSR_SOV; +if (SIGN & ((AX ^ (AX + AY)) & (~AX ^ AY))) /* always calc SOV */ + MSR = MSR | MSR_SOV; else MSR = MSR & ~MSR_SOV; return AO; } @@ -769,10 +816,10 @@ return ao_update (); t_stat ao_fo (uint32 op) { -uint32 t = OP_GET_FOA (op); /* get func */ +uint32 t = OP_GET_FOA (op); /* get func */ -MSR = MSR_PUT_FOA (MSR, t); /* store in MSR */ -ao_update (); /* update AOV */ +MSR = MSR_PUT_FOA (MSR, t); /* store in MSR */ +ao_update (); /* update AOV */ return SCPE_OK; } @@ -780,48 +827,59 @@ 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; - } -else 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 */ - MSR = MSR & ~MSR_L; } /* clear link */ - else MSR = MSR | MSR_L; /* set link */ - } -else if (op == EAO_ARS) { /* arith right? */ - t = 0; /* shift limiter */ - if (AX & SIGN) MSR = MSR | MSR_L; /* L = sign */ - else MSR = MSR & ~MSR_L; - do { /* shift one bit */ - AY = ((AY >> 1) | (AX << 15)) & DMASK; - AX = (AX & SIGN) | (AX >> 1); - GR[0] = (GR[0] + 1) & DMASK; } - while (GR[0] && (++t < 32)); /* until cnt or limit */ - } -else if (op == EAO_NORM) { /* norm? */ - if ((AX | AY) != 0) { /* can normalize? */ - while ((AX & SIGN) != ((AX << 1) & SIGN)) { /* until AX15 != AX14 */ - AX = ((AX << 1) | (AY >> 15)) & DMASK; - AY = (AY << 1) & DMASK; - GR[0] = (GR[0] + 1) & DMASK; } } - } +if (cpu_unit.flags & UNIT_NOEAO) return stop_opr; /* EAO installed? */ +switch (op) { + + case EAO_MUL: /* mul? */ + t = AX * AY; /* AX * AY */ + AX = (t >> 16) & DMASK; /* to AX'GR1 */ + GR[0] = t & DMASK; + break; + + case 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 */ + MSR = MSR & ~MSR_L; /* clear link */ + } + else MSR = MSR | MSR_L; /* set link */ + break; + + case EAO_ARS: /* arith right? */ + t = 0; /* shift limiter */ + if (AX & SIGN) MSR = MSR | MSR_L; /* L = sign */ + else MSR = MSR & ~MSR_L; + do { /* shift one bit */ + AY = ((AY >> 1) | (AX << 15)) & DMASK; + AX = (AX & SIGN) | (AX >> 1); + GR[0] = (GR[0] + 1) & DMASK; + } + while (GR[0] && (++t < 32)); /* until cnt or limit */ + break; + + case EAO_NORM: /* norm? */ + if ((AX | AY) != 0) { /* can normalize? */ + while ((AX & SIGN) != ((AX << 1) & SIGN)) { /* until AX15 != AX14 */ + AX = ((AX << 1) | (AY >> 15)) & DMASK; + AY = (AY << 1) & DMASK; + GR[0] = (GR[0] + 1) & DMASK; + } + } + break; + } + ao_update (); return SCPE_OK; } uint32 ao_sf (uint32 op) { -if (((op & 2) && (MSR & MSR_AOV)) || /* arith carry? */ - ((op & 4) && (MSR & MSR_SOV))) return 1; /* arith overflow? */ +if (((op & 2) && (MSR & MSR_AOV)) || /* arith carry? */ + ((op & 4) && (MSR & MSR_SOV))) return 1; /* arith overflow? */ return 0; } - + /* Byte swapper (24) */ uint32 bsw_rd (uint32 src) @@ -860,7 +918,7 @@ t_stat gr_wr (uint32 dst, uint32 dat) GR[dst - U_GR] = dat; return SCPE_OK; } - + /* Reset routine */ t_stat cpu_reset (DEVICE *dptr) @@ -906,10 +964,10 @@ int32 mc = 0; uint32 i; if ((val <= 0) || (val > MAXMEMSIZE) || ((val & 07777) != 0)) - return SCPE_ARG; + 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; + 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 index 0aff682b..dacc88f5 100644 --- a/GRI/gri_defs.h +++ b/GRI/gri_defs.h @@ -19,12 +19,12 @@ 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 + 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 + 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 @@ -50,174 +50,174 @@ Answer: arithmetic right shift, normalize. */ -#include "sim_defs.h" /* simulator defns */ +#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 */ +#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) +#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 */ +#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 */ +#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 */ +#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 030 /* hex general regs */ -#define U_RTC 075 /* clock */ -#define U_HS 076 /* paper tape */ -#define U_TTY 077 /* console */ +#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 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 */ + 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 */ +#define TRP_DIR 00 /* direct */ +#define TRP_DEF 01 /* defer */ /* Interrupt status */ -#define ISR_OFF 01 /* int off */ -#define ISR_ON 02 /* int on */ +#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 */ +#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 */ +#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_ARS 03 /* arith rshft */ -#define EAO_NORM 04 /* normalize */ +#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_ARS 03 /* arith rshft */ +#define EAO_NORM 04 /* normalize */ /* Machine status */ -#define MSR_V_BOV 15 /* bus carry */ -#define MSR_V_L 14 /* bus link */ -#define MSR_V_FOA 8 /* arith func */ -#define MSR_M_FOA 03 -#define MSR_V_SOV 1 /* arith ovflo */ -#define MSR_V_AOV 0 /* arith carry */ -#define MSR_BOV (1u << MSR_V_BOV) -#define MSR_L (1u << MSR_V_L) -#define MSR_FOA (MSR_M_FOA << MSR_V_FOA) -#define MSR_SOV (1u << MSR_V_SOV) -#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)) -#define MSR_RW (MSR_BOV|MSR_L|MSR_FOA|MSR_SOV|MSR_AOV) +#define MSR_V_BOV 15 /* bus carry */ +#define MSR_V_L 14 /* bus link */ +#define MSR_V_FOA 8 /* arith func */ +#define MSR_M_FOA 03 +#define MSR_V_SOV 1 /* arith ovflo */ +#define MSR_V_AOV 0 /* arith carry */ +#define MSR_BOV (1u << MSR_V_BOV) +#define MSR_L (1u << MSR_V_L) +#define MSR_FOA (MSR_M_FOA << MSR_V_FOA) +#define MSR_SOV (1u << MSR_V_SOV) +#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)) +#define MSR_RW (MSR_BOV|MSR_L|MSR_FOA|MSR_SOV|MSR_AOV) /* 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 */ +#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 */ +#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 */ +#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) +#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 */ +#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 index c7fbfc13..295a22d3 100644 --- a/GRI/gri_doc.txt +++ b/GRI/gri_doc.txt @@ -27,8 +27,8 @@ The following copyright notice applies to both the SIMH source and binary: 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 + 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. diff --git a/GRI/gri_stddev.c b/GRI/gri_stddev.c index 7f55f978..6d6e5cb4 100644 --- a/GRI/gri_stddev.c +++ b/GRI/gri_stddev.c @@ -1,6 +1,6 @@ /* gri_stddev.c: GRI-909 standard devices - Copyright (c) 2001-2004, Robert M Supnik + Copyright (c) 2001-2005, 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"), @@ -19,29 +19,29 @@ 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 + 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 + 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 - 29-Dec-03 RMS Added support for console backpressure - 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 + 29-Dec-03 RMS Added support for console backpressure + 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) +#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; @@ -60,152 +60,166 @@ 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 + 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 } }; + { 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 } }; + { 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 }; + "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 + 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 } }; + { 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 } }; + { 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 }; - + "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 + 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 }; + 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 } }; + { 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 }; + "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 + 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 }; + 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 } }; + { 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 }; - + "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 + 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 } }; + { 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 }; - + "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 */ +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 */ +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; } @@ -229,15 +243,16 @@ 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 */ +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 */ +dev_done = dev_done | INT_TTI; /* set ready */ tti_unit.pos = tti_unit.pos + 1; return SCPE_OK; } @@ -247,14 +262,16 @@ t_stat tto_svc (UNIT *uptr) int32 c; t_stat r; -if (tto_unit.flags & UNIT_KSR) { /* KSR? */ - c = tto_unit.buf & 0177; /* force 7b */ - if (islower (c)) c = toupper (c); } /* cvt to UC */ +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_s (c)) != SCPE_OK) { /* output; error? */ - sim_activate (uptr, uptr->wait); /* try again */ - return ((r == SCPE_STALL)? SCPE_OK: r); } /* !stall? report */ -dev_done = dev_done | INT_TTO; /* set ready */ +if ((r = sim_putchar_s (c)) != SCPE_OK) { /* output; error? */ + sim_activate (uptr, uptr->wait); /* try again */ + return ((r == SCPE_STALL)? SCPE_OK: r); /* !stall? report */ + } +dev_done = dev_done | INT_TTO; /* set ready */ tto_unit.pos = tto_unit.pos + 1; return SCPE_OK; } @@ -263,17 +280,17 @@ return SCPE_OK; 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 */ +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 */ +tto_unit.buf = 0; /* clear buffer */ +dev_done = dev_done | INT_TTO; /* set ready */ +sim_cancel (&tto_unit); /* deactivate unit */ return SCPE_OK; } @@ -283,19 +300,19 @@ 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 */ +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 */ +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; } @@ -318,30 +335,33 @@ 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 */ +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; } +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; } @@ -350,28 +370,28 @@ return SCPE_OK; 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 */ +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 */ +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? */ +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; } @@ -383,15 +403,15 @@ 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 */ +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 */ +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 index 9bd8a41c..2d7a89d5 100644 --- a/GRI/gri_sys.c +++ b/GRI/gri_sys.c @@ -1,6 +1,6 @@ /* gri_sys.c: GRI-909 simulator interface - Copyright (c) 2001-2004, Robert M Supnik + Copyright (c) 2001-2005, 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"), @@ -19,11 +19,11 @@ 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 + 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) + 18-Oct-02 RMS Fixed bug in symbolic decode (found by Hans Pufal) */ #include "gri_defs.h" @@ -40,12 +40,12 @@ 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 + 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"; @@ -55,21 +55,23 @@ 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 }; + &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" }; - + "Unknown error", + "Unimplemented unit", + "HALT instruction", + "Breakpoint", + "Invalid interrupt request" + }; + /* Binary loader Bootstrap loader format consists of blocks separated by zeroes. Each @@ -85,78 +87,81 @@ 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 */ +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 */ +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_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) +#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 */ + 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 }; + 0176000, 0176077, 0000077, 0176077, + 0000300, 0176300, 0000300, 0177777, + 0000077, 0177777, 0000377, 0176377, + 0176300, 0176377 + }; /* Instruction mnemonics @@ -174,17 +179,18 @@ static const int32 masks[] = { */ 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 */ + "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 */ + "JO", "JOD", "JN", "JND", /* JU before JC */ "JU", "JUD", "JC", "JCD", - "ZR", "ZRC", "RR", "RRC", /* ZR before RR */ + "ZR", "ZRC", "RR", "RRC", /* ZR before RR */ "RS", "RSC", - NULL }; + NULL + }; static const uint32 opc_val[] = { 0004000+F_FOI, 0004013+F_FOI, 0004004+F_FOI, 0004000+F_FO, @@ -196,77 +202,84 @@ static const uint32 opc_val[] = { 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 }; + 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 */ + "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 */ + "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 */ + "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 */ + "70", "71", "72", "73", "74", "RTC", "HSP", "TTO" /* 70 - 77 */ + }; - /* Operators */ + /* Operators */ static const char *opname[4] = { - NULL, "P1", "L1", "R1" }; + NULL, "P1", "L1", "R1" + }; /* Conditions */ static const char *cdname[8] = { - "NEVER", "ALWAYS", "ETZ", "NEZ", "LTZ", "GEZ", "LEZ", "GTZ" }; + "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 }; + "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 */ - + { 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) @@ -274,13 +287,14 @@ 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 (((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; } @@ -288,117 +302,136 @@ return; /* Symbolic decode Inputs: - *of = output stream - addr = current PC - *val = pointer to data - *uptr = pointer to unit - sw = switches + *of = output stream + addr = current PC + *val = pointer to data + *uptr = pointer to unit + sw = switches Outputs: - return = status code + 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) + 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 ('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 */ +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? */ +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 */ + 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 + 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) @@ -411,23 +444,27 @@ 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 */ + 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; } @@ -437,10 +474,10 @@ 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] */ +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 */ +val[1] = d; /* second wd */ return cptr; } @@ -450,14 +487,16 @@ 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 */ +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; } @@ -466,24 +505,26 @@ 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 */ +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 + *cptr = pointer to input string + addr = current PC + *uptr = pointer to unit + *val = pointer to output values + sw = switches Outputs: - status = error status + status = error status */ t_stat parse_sym (char *cptr, t_addr addr, UNIT *uptr, t_value *val, int32 sw) @@ -491,92 +532,109 @@ 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 */ +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 (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; } - + 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 */ +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 */ +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? */ +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; + } /* end case */ + +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 index a41f6de2..6c2b04b7 100644 --- a/H316/h316_cpu.c +++ b/H316/h316_cpu.c @@ -19,35 +19,36 @@ 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 + 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 + cpu H316/H516 CPU - 15-Feb-05 RMS Added start button interrupt - 01-Dec-04 RMS Fixed bug in DIV - 06-Nov-04 RMS Added =n to SHOW HISTORY - 04-Jan-04 RMS Removed unnecessary compare - 31-Dec-03 RMS Fixed bug in cpu_set_hist - 24-Oct-03 RMS Added DMA/DMC support, instruction history - 30-Dec-01 RMS Added old PC queue - 03-Nov-01 RMS Fixed NOHSA modifier - 30-Nov-01 RMS Added extended SET/SHOW support + 16-Aug-05 RMS Fixed C++ declaration and cast problems + 15-Feb-05 RMS Added start button interrupt + 01-Dec-04 RMS Fixed bug in DIV + 06-Nov-04 RMS Added =n to SHOW HISTORY + 04-Jan-04 RMS Removed unnecessary compare + 31-Dec-03 RMS Fixed bug in cpu_set_hist + 24-Oct-03 RMS Added DMA/DMC support, instruction history + 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 + 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. @@ -59,47 +60,46 @@ |in|xr| op |sc| offset | memory reference +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - <13:10> mnemonic action + <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 + 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 + <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] + 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: + + The control format is: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ @@ -153,9 +153,8 @@ 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 + + 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. @@ -164,17 +163,17 @@ 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 + 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_int device interrupt flags - dev_enb device interrupt enable flags + dev_int device interrupt flags + dev_enb device interrupt enable flags In addition, dev_int contains the interrupt enable and interrupt no defer flags. If interrupt enable and interrupt no defer are set, and @@ -189,76 +188,78 @@ 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 + 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 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 +#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 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 -#define HIST_PC 0x40000000 -#define HIST_C 0x20000000 -#define HIST_EA 0x10000000 -#define HIST_MIN 64 -#define HIST_MAX 65536 -struct InstHistory { - int32 pc; - int32 ir; - int32 ar; - int32 br; - int32 xr; - int32 ea; - int32 opnd; }; +#define HIST_PC 0x40000000 +#define HIST_C 0x20000000 +#define HIST_EA 0x10000000 +#define HIST_MIN 64 +#define HIST_MAX 65536 -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_int = 0; /* dev ready */ -int32 dev_enb = 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 */ -uint32 dma_nch = DMA_MAX; /* number of chan */ -uint32 dma_ad[DMA_MAX] = { 0 }; /* DMA addresses */ -uint32 dma_wc[DMA_MAX] = { 0 }; /* DMA word count */ -uint32 dma_eor[DMA_MAX] = { 0 }; /* DMA end of range */ -uint32 chan_req = 0; /* channel requests */ -uint32 chan_map[DMA_MAX + DMC_MAX] = { 0 }; /* chan->dev map */ +typedef struct { + int32 pc; + int32 ir; + int32 ar; + int32 br; + int32 xr; + int32 ea; + int32 opnd; + } InstHistory; + +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_int = 0; /* dev ready */ +int32 dev_enb = 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 */ +uint32 dma_nch = DMA_MAX; /* number of chan */ +uint32 dma_ad[DMA_MAX] = { 0 }; /* DMA addresses */ +uint32 dma_wc[DMA_MAX] = { 0 }; /* DMA word count */ +uint32 dma_eor[DMA_MAX] = { 0 }; /* DMA end of range */ +uint32 chan_req = 0; /* channel requests */ +uint32 chan_map[DMA_MAX + DMC_MAX] = { 0 }; /* chan->dev map */ int32 (*iotab[DEV_MAX])(int32 inst, int32 fnc, int32 dat, int32 dev) = { NULL }; -int32 hst_p = 0; /* history pointer */ -int32 hst_lnt = 0; /* history length */ -struct InstHistory *hst = NULL; /* instruction history */ +int32 hst_p = 0; /* history pointer */ +int32 hst_lnt = 0; /* history length */ +InstHistory *hst = NULL; /* 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 int32 sim_brk_types, sim_brk_dflt, sim_brk_summ; /* breakpoint info */ extern FILE *sim_log; extern DEVICE *sim_devices[]; @@ -277,90 +278,94 @@ t_stat cpu_set_nchan (UNIT *uptr, int32 val, char *cptr, void *desc); t_stat cpu_show_nchan (FILE *st, UNIT *uptr, int32 val, void *desc); extern t_stat fprint_sym (FILE *of, t_addr addr, t_value *val, - UNIT *uptr, int32 sw); - + 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 + cpu_dev CPU device descriptor + cpu_unit CPU unit descriptor + cpu_reg CPU register list + cpu_mod CPU modifiers list */ DIB cpu_dib = { DMA, IOBUS, 1, &dmaio }; -UNIT cpu_unit = { UDATA (NULL, UNIT_FIX+UNIT_BINK+UNIT_EXT+UNIT_HSA+UNIT_DMC, - MAXMEMSIZE) }; +UNIT cpu_unit = { + UDATA (NULL, UNIT_FIX+UNIT_BINK+UNIT_EXT+UNIT_HSA+UNIT_DMC, 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_int, INT_V_ON) }, - { FLDATA (INODEF, dev_int, INT_V_NODEF) }, - { FLDATA (START, dev_int, INT_V_START) }, - { ORDATA (DEVINT, dev_int, 16), REG_RO }, - { ORDATA (DEVENB, dev_enb, 16), REG_RO }, - { ORDATA (CHREQ, chan_req, DMA_MAX + DMC_MAX) }, - { BRDATA (DMAAD, dma_ad, 8, 16, DMA_MAX) }, - { BRDATA (DMAWC, dma_wc, 8, 16, DMA_MAX) }, - { BRDATA (DMAEOR, dma_eor, 8, 1, DMA_MAX) }, - { ORDATA (DMANCH, dma_nch, 3), REG_HRO }, - { FLDATA (MPERDY, dev_int, INT_V_MPE) }, - { FLDATA (MPEENB, dev_enb, 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) }, - { NULL } }; + { 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_int, INT_V_ON) }, + { FLDATA (INODEF, dev_int, INT_V_NODEF) }, + { FLDATA (START, dev_int, INT_V_START) }, + { ORDATA (DEVINT, dev_int, 16), REG_RO }, + { ORDATA (DEVENB, dev_enb, 16), REG_RO }, + { ORDATA (CHREQ, chan_req, DMA_MAX + DMC_MAX) }, + { BRDATA (DMAAD, dma_ad, 8, 16, DMA_MAX) }, + { BRDATA (DMAWC, dma_wc, 8, 16, DMA_MAX) }, + { BRDATA (DMAEOR, dma_eor, 8, 1, DMA_MAX) }, + { ORDATA (DMANCH, dma_nch, 3), REG_HRO }, + { FLDATA (MPERDY, dev_int, INT_V_MPE) }, + { FLDATA (MPEENB, dev_enb, 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) }, + { 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 }, - { MTAB_XTD | MTAB_VDV, 0, "channels", "CHANNELS", - &cpu_set_nchan, &cpu_show_nchan, NULL }, - { UNIT_DMC, 0, "no DMC", "NODMC", NULL }, - { UNIT_DMC, UNIT_DMC, "DMC", "DMC", NULL }, - { MTAB_XTD|MTAB_VDV|MTAB_NMO|MTAB_SHP, 0, "HISTORY", "HISTORY", - &cpu_set_hist, &cpu_show_hist }, - { MTAB_XTD | MTAB_VDV | MTAB_NMO, 0, "DMA1", NULL, - NULL, &cpu_show_dma, NULL }, - { MTAB_XTD | MTAB_VDV | MTAB_NMO, 1, "DMA2", NULL, - NULL, &cpu_show_dma, NULL }, - { MTAB_XTD | MTAB_VDV | MTAB_NMO, 2, "DMA3", NULL, - NULL, &cpu_show_dma, NULL }, - { MTAB_XTD | MTAB_VDV | MTAB_NMO, 3, "DMA4", NULL, - NULL, &cpu_show_dma, NULL }, - { 0 } }; + { 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 }, + { MTAB_XTD | MTAB_VDV, 0, "channels", "CHANNELS", + &cpu_set_nchan, &cpu_show_nchan, NULL }, + { UNIT_DMC, 0, "no DMC", "NODMC", NULL }, + { UNIT_DMC, UNIT_DMC, "DMC", "DMC", NULL }, + { MTAB_XTD|MTAB_VDV|MTAB_NMO|MTAB_SHP, 0, "HISTORY", "HISTORY", + &cpu_set_hist, &cpu_show_hist }, + { MTAB_XTD | MTAB_VDV | MTAB_NMO, 0, "DMA1", NULL, + NULL, &cpu_show_dma, NULL }, + { MTAB_XTD | MTAB_VDV | MTAB_NMO, 1, "DMA2", NULL, + NULL, &cpu_show_dma, NULL }, + { MTAB_XTD | MTAB_VDV | MTAB_NMO, 2, "DMA3", NULL, + NULL, &cpu_show_dma, NULL }, + { MTAB_XTD | MTAB_VDV | MTAB_NMO, 3, "DMA4", NULL, + NULL, &cpu_show_dma, NULL }, + { 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, - &cpu_dib, 0 }; - + "CPU", &cpu_unit, cpu_reg, cpu_mod, + 1, 8, 15, 1, 8, 16, + &cpu_ex, &cpu_dep, &cpu_reset, + NULL, NULL, NULL, + &cpu_dib, 0 + }; + t_stat sim_instr (void) { extern UNIT clk_unit; @@ -373,514 +378,551 @@ int32 Add16 (int32 val1, int32 val2); int32 Add31 (int32 val1, int32 val2); int32 Operate (int32 MB, int32 AR); -#define Read(ad) M[(ad)] -#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))) +#define Read(ad) M[(ad)] +#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 */ -if (devtab_init ()) return SCPE_STOP; /* init tables */ -AR = saved_AR & DMASK; /* restore reg */ +if (devtab_init ()) return SCPE_STOP; /* init tables */ +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; -sim_rtc_init (clk_unit.wait); /* init calibration */ - +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; } +while (reason == 0) { /* loop until halted */ + +if (sim_interval <= 0) { /* check clock queue */ + if (reason = sim_process_event ()) break; + } /* Channel breaks (DMA and DMC) */ -if (chan_req) { /* channel request? */ - int32 i, t, ch, dev, st, end, ad, dmcad; - t_stat r; - for (i = 0, ch = chan_req; ch != 0; i++, ch = ch >> 1) { - if (ch & 1) { /* req on chan i? */ - dev = chan_map[i]; /* get dev for chan */ - if (iotab[dev] == &undio) return SCPE_IERR; - chan_req = chan_req & ~(1 << i); /* clear req */ - if (Q_DMA (i)) st = dma_ad[i]; /* DMA? */ - else { /* DMC */ - dmcad = DMC_BASE + ((i - DMC_V_DMC1) << 1); - st = Read (dmcad); } /* DMC ctrl word */ - ad = st & X_AMASK; /* get curr addr */ - if (st & DMA_IN) { /* input? */ - t = iotab[dev] (ioINA, 0, 0, dev); /* input word */ - if ((t & IOT_SKIP) == 0) return STOP_DMAER; - if (r = (t >> IOT_V_REASON)) return r; - Write (ad, t & DMASK); } /* write to mem */ - else { /* no, output */ - t = iotab[dev] (ioOTA, 0, Read (ad), dev); /* output word */ - if ((t & IOT_SKIP) == 0) return STOP_DMAER; - if (r = (t >> IOT_V_REASON)) return r; } - if (Q_DMA (i)) { /* DMA? */ - dma_ad[i] = (dma_ad[i] & DMA_IN) | ((ad + 1) & X_AMASK); - dma_wc[i] = (dma_wc[i] + 1) & 077777; /* update wc */ - if (dma_wc[i] == 0) { /* done? */ - dma_eor[i] = 1; /* set end of range */ - t = iotab[dev] (ioEND, 0, 0, dev); /* send end range */ - if (r = (t >> IOT_V_REASON)) return r; } } - else { /* DMC */ - st = (st & DMA_IN) | ((ad + 1) & X_AMASK); - Write (dmcad, st); /* update start */ - end = Read (dmcad + 1); /* get end */ - if (((ad ^ end) & X_AMASK) == 0) { /* start == end? */ - t = iotab[dev] (ioEND, 0, 0, dev); /* send end range */ - if (r = (t >> IOT_V_REASON)) return r; } } - } /* end if chan i */ - } /* end for */ - } /* end if chan_req */ +if (chan_req) { /* channel request? */ + int32 i, t, ch, dev, st, end, ad, dmcad; + t_stat r; + for (i = 0, ch = chan_req; ch != 0; i++, ch = ch >> 1) { + if (ch & 1) { /* req on chan i? */ + dev = chan_map[i]; /* get dev for chan */ + if (iotab[dev] == &undio) return SCPE_IERR; + chan_req = chan_req & ~(1 << i); /* clear req */ + if (Q_DMA (i)) st = dma_ad[i]; /* DMA? */ + else { /* DMC */ + dmcad = DMC_BASE + ((i - DMC_V_DMC1) << 1); + st = Read (dmcad); /* DMC ctrl word */ + } + ad = st & X_AMASK; /* get curr addr */ + if (st & DMA_IN) { /* input? */ + t = iotab[dev] (ioINA, 0, 0, dev); /* input word */ + if ((t & IOT_SKIP) == 0) return STOP_DMAER; + if (r = (t >> IOT_V_REASON)) return r; + Write (ad, t & DMASK); /* write to mem */ + } + else { /* no, output */ + t = iotab[dev] (ioOTA, 0, Read (ad), dev); /* output word */ + if ((t & IOT_SKIP) == 0) return STOP_DMAER; + if (r = (t >> IOT_V_REASON)) return r; + } + if (Q_DMA (i)) { /* DMA? */ + dma_ad[i] = (dma_ad[i] & DMA_IN) | ((ad + 1) & X_AMASK); + dma_wc[i] = (dma_wc[i] + 1) & 077777; /* update wc */ + if (dma_wc[i] == 0) { /* done? */ + dma_eor[i] = 1; /* set end of range */ + t = iotab[dev] (ioEND, 0, 0, dev); /* send end range */ + if (r = (t >> IOT_V_REASON)) return r; + } + } + else { /* DMC */ + st = (st & DMA_IN) | ((ad + 1) & X_AMASK); + Write (dmcad, st); /* update start */ + end = Read (dmcad + 1); /* get end */ + if (((ad ^ end) & X_AMASK) == 0) { /* start == end? */ + t = iotab[dev] (ioEND, 0, 0, dev); /* send end range */ + if (r = (t >> IOT_V_REASON)) return r; + } /* end if end range */ + } /* end else DMC */ + } /* end if chan i */ + } /* end for */ + } /* end if chan_req */ /* Interrupts */ if ((dev_int & (INT_PEND|INT_NMI|dev_enb)) > INT_PEND) {/* int req? */ - pme = ext; /* save extend */ - if (cpu_unit.flags & UNIT_EXT) ext = 1; /* ext opt? extend on */ - dev_int = dev_int & ~INT_ON; /* intr off */ - MB = 0120000 | M_INT; } /* inst = JST* 63 */ + pme = ext; /* save extend */ + if (cpu_unit.flags & UNIT_EXT) ext = 1; /* ext opt? extend on */ + dev_int = dev_int & ~INT_ON; /* intr off */ + MB = 0120000 | M_INT; /* inst = JST* 63 */ + } /* Instruction fetch */ -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_int = dev_int | INT_NODEF; } +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_int = dev_int | INT_NODEF; + } -dev_int = dev_int & ~INT_START; /* clr start button int */ +dev_int = dev_int & ~INT_START; /* clr start button int */ sim_interval = sim_interval - 1; -if (hst_lnt) { /* instr hist? */ - hst_p = (hst_p + 1); /* next entry */ - if (hst_p >= hst_lnt) hst_p = 0; - hst[hst_p].pc = Y | HIST_PC | (C? HIST_C: 0); /* fill slots */ - hst[hst_p].ir = MB; - hst[hst_p].ar = AR; - hst[hst_p].br = BR; - hst[hst_p].xr = XR; } - +if (hst_lnt) { /* instr hist? */ + hst_p = (hst_p + 1); /* next entry */ + if (hst_p >= hst_lnt) hst_p = 0; + hst[hst_p].pc = Y | HIST_PC | (C? HIST_C: 0); /* fill slots */ + hst[hst_p].ir = MB; + hst[hst_p].ar = AR; + hst[hst_p].br = BR; + hst[hst_p].xr = XR; + } + /* Memory reference instructions */ -switch (I_GETOP (MB)) { /* case on <1:6> */ +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 (extoff_pending) ext = extoff_pending = 0; /* cond ext off */ - break; + 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 (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 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 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 */ - Write (Y, AR); /* store A */ - if (dp) { /* double prec? */ - Write (Y | 1, BR); /* store B */ - sc = 0; } - break; + case 004: case 024: case 044: case 064: /* STA */ + if (reason = Ea (MB, &Y)) break; /* eff addr */ + Write (Y, AR); /* store A */ + if (dp) { /* double prec? */ + Write (Y | 1, BR); /* store B */ + sc = 0; + } + break; -case 005: case 025: case 045: case 065: /* ERA */ - if (reason = Ea (MB, &Y)) break; /* eff addr */ - AR = AR ^ Read (Y); - 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 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 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; -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 (Y, MB); - PCQ_ENTRY; - PC = NEWA (PC, Y + 1); /* set new PC */ - break; + 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 (Y, MB); + 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 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 (Y, MB); - if (MB == 0) PC = NEWA (PC, PC + 1); /* skip if zero */ - 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 (Y, MB); + 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 (Y, AR); /* A to mem */ - AR = MB; /* mem to A */ - break; + case 013: case 033: case 053: case 073: /* IMA */ + if (reason = Ea (MB, &Y)) break; /* eff addr */ + MB = Read (Y); + Write (Y, AR); /* A to mem */ + AR = MB; /* mem to A */ + break; -case 015: case 055: /* STX */ - if (reason = Ea (MB & ~IDX, &Y)) break; /* eff addr */ - Write (Y, XR); /* store XR */ - break; + case 015: case 055: /* STX */ + if (reason = Ea (MB & ~IDX, &Y)) break; /* eff addr */ + Write (Y, XR); /* store XR */ + break; -case 035: case 075: /* LDX */ - if (reason = Ea (MB & ~IDX, &Y)) break; /* eff addr */ - XR = Read (Y); /* load 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 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 (SEXT (AR), BR); /* get A'B signed */ + 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; -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 (SEXT (AR), BR); /* get A'B signed */ - 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 */ - dev = MB & DEVMASK; - t2 = iotab[dev] (ioOCP, I_GETFNC (MB), AR, dev); - reason = t2 >> IOT_V_REASON; - break; + case 014: /* OCP */ + dev = MB & DEVMASK; + t2 = iotab[dev] (ioOCP, I_GETFNC (MB), AR, dev); + reason = t2 >> IOT_V_REASON; + break; -case 034: /* SKS */ - dev = MB & DEVMASK; - t2 = iotab[dev] (ioSKS, I_GETFNC (MB), AR, dev); - reason = t2 >> IOT_V_REASON; - if (t2 & IOT_SKIP) PC = NEWA (PC, PC + 1); /* skip? */ - break; + case 034: /* SKS */ + dev = MB & DEVMASK; + t2 = iotab[dev] (ioSKS, I_GETFNC (MB), AR, dev); + reason = t2 >> IOT_V_REASON; + if (t2 & IOT_SKIP) PC = NEWA (PC, PC + 1); /* skip? */ + break; -case 054: /* INA */ - dev = MB & DEVMASK; - if (MB & INCLRA) AR = 0; - t2 = iotab[dev] (ioINA, I_GETFNC (MB & ~INCLRA), AR, dev); - reason = t2 >> IOT_V_REASON; - if (t2 & IOT_SKIP) PC = NEWA (PC, PC + 1); /* skip? */ - AR = t2 & DMASK; /* data */ - break; + case 054: /* INA */ + dev = MB & DEVMASK; + if (MB & INCLRA) AR = 0; + t2 = iotab[dev] (ioINA, I_GETFNC (MB & ~INCLRA), AR, dev); + reason = t2 >> IOT_V_REASON; + if (t2 & IOT_SKIP) PC = NEWA (PC, PC + 1); /* skip? */ + AR = t2 & DMASK; /* data */ + break; + + case 074: /* OTA */ + dev = MB & DEVMASK; + t2 = iotab[dev] (ioOTA, I_GETFNC (MB), AR, dev); + reason = t2 >> IOT_V_REASON; + if (t2 & IOT_SKIP) PC = NEWA (PC, PC + 1); /* skip? */ + break; -case 074: /* OTA */ - dev = MB & DEVMASK; - t2 = iotab[dev] (ioOTA, I_GETFNC (MB), AR, dev); - reason = t2 >> IOT_V_REASON; - if (t2 & IOT_SKIP) PC = NEWA (PC, PC + 1); /* skip? */ - 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) CLR_INT (INT_MPE); /* RMP */ - 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_int = (dev_int | INT_ON) & ~INT_NODEF; - if (MB & m7) /* INH */ - dev_int = dev_int & ~INT_ON; - break; - + 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) CLR_INT (INT_MPE); /* RMP */ + 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_int = (dev_int | INT_ON) & ~INT_NODEF; + if (MB & m7) /* INH */ + dev_int = dev_int & ~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 + 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 + 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 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 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 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 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 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 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 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 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 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; - 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 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 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 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 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 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 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 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; - 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; - + 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 */ + 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 */ +pcq_r->qptr = pcq_p; /* update pc q ptr */ return reason; } - + /* Effective address The effective address calculation consists of three phases: @@ -899,26 +941,29 @@ return reason; t_stat Ea (int32 IR, int32 *addr) { int32 i; -int32 Y = IR & (IA | DISP); /* ind + disp */ +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 (hst_lnt) { /* history? */ - hst[hst_p].pc = hst[hst_p].pc | HIST_EA; - hst[hst_p].ea = Y; - hst[hst_p].opnd = Read (Y); } -if (i >= ind_max) return STOP_IND; /* too many ind? */ +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 (hst_lnt) { /* history? */ + hst[hst_p].pc = hst[hst_p].pc | HIST_EA; + hst[hst_p].ea = Y; + hst[hst_p].opnd = Read (Y); + } +if (i >= ind_max) return STOP_IND; /* too many ind? */ return SCPE_OK; } @@ -927,7 +972,7 @@ return SCPE_OK; void Write (int32 addr, int32 val) { if (((addr == 0) || (addr >= 020)) && MEM_ADDR_OK (addr)) - M[addr] = val; + M[addr] = val; return; } @@ -964,24 +1009,30 @@ int32 dmaio (int32 inst, int32 fnc, int32 dat, int32 dev) { int32 ch = (fnc - 1) & 03; -switch (inst) { /* case on opcode */ -case ioOCP: /* OCP */ - if ((fnc >= 001) && (fnc <= 004)) { /* load addr ctr */ - dma_ad[ch] = dat; - dma_wc[ch] = 0; - dma_eor[ch] = 0; } - else if ((fnc >= 011) && (fnc <= 014)) /* load range ctr */ - dma_wc[ch] = (dma_wc[ch] | dat) & 077777; - else return IOBADFNC (dat); /* undefined */ - break; -case ioINA: /* INA */ - if ((fnc >= 011) && (fnc <= 014)) { - if (dma_eor[ch]) return dat; /* end range? nop */ - return IOSKIP (0100000 | dma_wc[ch]); } /* return range */ - else return IOBADFNC (dat); } +switch (inst) { /* case on opcode */ + + case ioOCP: /* OCP */ + if ((fnc >= 001) && (fnc <= 004)) { /* load addr ctr */ + dma_ad[ch] = dat; + dma_wc[ch] = 0; + dma_eor[ch] = 0; + } + else if ((fnc >= 011) && (fnc <= 014)) /* load range ctr */ + dma_wc[ch] = (dma_wc[ch] | dat) & 077777; + else return IOBADFNC (dat); /* undefined */ + break; + + case ioINA: /* INA */ + if ((fnc >= 011) && (fnc <= 014)) { + if (dma_eor[ch]) return dat; /* end range? nop */ + return IOSKIP (0100000 | dma_wc[ch]); /* return range */ + } + else return IOBADFNC (dat); + } + return dat; } - + /* 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. @@ -989,66 +1040,66 @@ return dat; 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 + 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 + 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) + 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) + 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 - } + 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) + 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; @@ -1058,70 +1109,72 @@ 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 */ +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 */ + 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 */ +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 */ +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 + 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 + 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 && + if (!jamkn && ((bleg && !eiki7 && (D == 0077777)) || - (!bleg && eiki7 && (D == 0100000)))) C = 1; - else C = 0; } -if (cbite || (cbitg && (D & SIGN))) C = 1; /* C = 1 */ + (!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) @@ -1181,10 +1234,10 @@ uint32 i; if ((val <= 0) || (val > MAXMEMSIZE) || ((val & 07777) != 0) || (((cpu_unit.flags & UNIT_EXT) == 0) && (val > (NX_AMASK + 1)))) - return SCPE_ARG; + 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; + return SCPE_OK; MEMSIZE = val; for (i = MEMSIZE; i < MAXMEMSIZE; i++) M[i] = 0; return SCPE_OK; @@ -1196,12 +1249,13 @@ uint32 i, newmax; t_stat r; if (cptr == NULL) return SCPE_ARG; -newmax = get_uint (cptr, 10, DMA_MAX, &r); /* get new max */ -if ((r != SCPE_OK) || (newmax == dma_nch)) return r; /* err or no chg? */ -dma_nch = newmax; /* set new max */ -for (i = newmax; i < DMA_MAX; i++) { /* reset chan */ - dma_ad[i] = dma_wc[i] = dma_eor[i] = 0; - chan_req = chan_req & ~(1 << i); } +newmax = get_uint (cptr, 10, DMA_MAX, &r); /* get new max */ +if ((r != SCPE_OK) || (newmax == dma_nch)) return r; /* err or no chg? */ +dma_nch = newmax; /* set new max */ +for (i = newmax; i < DMA_MAX; i++) { /* reset chan */ + dma_ad[i] = dma_wc[i] = dma_eor[i] = 0; + chan_req = chan_req & ~(1 << i); + } return SCPE_OK; } @@ -1254,9 +1308,9 @@ if (dptr == NULL) return SCPE_IERR; dibp = (DIB *) dptr->ctxt; if (dibp == NULL) return SCPE_IERR; if (dma_nch == 0) return SCPE_NOFNC; -newc = get_uint (cptr, 10, DMA_MAX, &r); /* get new */ +newc = get_uint (cptr, 10, DMA_MAX, &r); /* get new */ if ((r != SCPE_OK) || (newc == 0) || (newc > dma_nch)) return SCPE_ARG; -dibp->chan = (newc - DMA_MIN) + DMA_V_DMA1 + 1; /* store */ +dibp->chan = (newc - DMA_MIN) + DMA_V_DMA1 + 1; /* store */ return SCPE_OK; } @@ -1273,9 +1327,9 @@ if (dptr == NULL) return SCPE_IERR; dibp = (DIB *) dptr->ctxt; if (dibp == NULL) return SCPE_IERR; if (!(cpu_unit.flags & UNIT_DMC)) return SCPE_NOFNC; -newc = get_uint (cptr, 10, DMC_MAX, &r); /* get new */ +newc = get_uint (cptr, 10, DMC_MAX, &r); /* get new */ if ((r != SCPE_OK) || (newc == 0)) return SCPE_ARG; -dibp->chan = (newc - DMC_MIN) + DMC_V_DMC1 + 1; /* store */ +dibp->chan = (newc - DMC_MIN) + DMC_V_DMC1 + 1; /* store */ return SCPE_OK; } @@ -1293,7 +1347,7 @@ dibp = (DIB *) dptr->ctxt; if (dibp == NULL) return SCPE_IERR; if (dibp->chan == 0) fprintf (st, "IO bus"); else if (dibp->chan < (DMC_V_DMC1 + 1)) - fprintf (st, "DMA channel %d", dibp->chan); + fprintf (st, "DMA channel %d", dibp->chan); else fprintf (st, "DMC channel %d", dibp->chan - DMC_V_DMC1); return SCPE_OK; } @@ -1308,39 +1362,45 @@ uint32 i, j, dno, chan; for (i = 0; i < DEV_MAX; i++) iotab[i] = NULL; for (i = 0; i < (DMA_MAX + DMC_MAX); i++) chan_map[i] = 0; -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->dev; /* device number */ - for (j = 0; j < dibp->num; j++) { /* repeat for slots */ - if (iotab[dno + j]) { /* conflict? */ - printf ("%s device number conflict, devno = %02o\n", sim_dname (dptr), dno + j); - if (sim_log) fprintf (sim_log, - "%s device number conflict, devno = %02o\n", sim_dname (dptr), dno + j); - return TRUE; } - iotab[dno + j] = dibp->io; /* set I/O routine */ - } /* end for */ - if (dibp->chan) { /* DMA/DMC? */ - chan = dibp->chan - 1; - if ((chan < DMC_V_DMC1) && (chan >= dma_nch)) { - printf ("%s configured for DMA channel %d\n", sim_dname (dptr), chan + 1); - if (sim_log) fprintf (sim_log, - "%s configured for DMA channel %d\n", sim_dname (dptr), chan + 1); - return TRUE; } - if ((chan >= DMC_V_DMC1) && !(cpu_unit.flags & UNIT_DMC)) { - printf ("%s configured for DMC, option disabled\n", sim_dname (dptr)); - if (sim_log) fprintf (sim_log, - "%s configured for DMC, option disabled\n", sim_dname (dptr)); - return TRUE; } - if (chan_map[chan]) { /* channel conflict? */ - printf ("%s DMA/DMC channel conflict, devno = %02o\n", sim_dname (dptr), dno); - if (sim_log) fprintf (sim_log, - "%s DMA/DMC channel conflict, devno = %02o\n", sim_dname (dptr), dno); - return TRUE; } - chan_map[chan] = dno; } /* channel back map */ - } /* end for */ -for (i = 0; i < DEV_MAX; i++) { /* fill in blanks */ - if (iotab[i] == NULL) iotab[i] = &undio; } +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->dev; /* device number */ + for (j = 0; j < dibp->num; j++) { /* repeat for slots */ + if (iotab[dno + j]) { /* conflict? */ + printf ("%s device number conflict, devno = %02o\n", sim_dname (dptr), dno + j); + if (sim_log) fprintf (sim_log, + "%s device number conflict, devno = %02o\n", sim_dname (dptr), dno + j); + return TRUE; + } + iotab[dno + j] = dibp->io; /* set I/O routine */ + } /* end for */ + if (dibp->chan) { /* DMA/DMC? */ + chan = dibp->chan - 1; + if ((chan < DMC_V_DMC1) && (chan >= dma_nch)) { + printf ("%s configured for DMA channel %d\n", sim_dname (dptr), chan + 1); + if (sim_log) fprintf (sim_log, + "%s configured for DMA channel %d\n", sim_dname (dptr), chan + 1); + return TRUE; + } + if ((chan >= DMC_V_DMC1) && !(cpu_unit.flags & UNIT_DMC)) { + printf ("%s configured for DMC, option disabled\n", sim_dname (dptr)); + if (sim_log) fprintf (sim_log, + "%s configured for DMC, option disabled\n", sim_dname (dptr)); + return TRUE; + } + if (chan_map[chan]) { /* channel conflict? */ + printf ("%s DMA/DMC channel conflict, devno = %02o\n", sim_dname (dptr), dno); + if (sim_log) fprintf (sim_log, + "%s DMA/DMC channel conflict, devno = %02o\n", sim_dname (dptr), dno); + return TRUE; + } + chan_map[chan] = dno; /* channel back map */ + } + } /* end for */ +for (i = 0; i < DEV_MAX; i++) { /* fill in blanks */ + if (iotab[i] == NULL) iotab[i] = &undio; + } return FALSE; } @@ -1352,20 +1412,23 @@ int32 i, lnt; t_stat r; if (cptr == NULL) { - for (i = 0; i < hst_lnt; i++) hst[i].pc = 0; - hst_p = 0; - return SCPE_OK; } + for (i = 0; i < hst_lnt; i++) hst[i].pc = 0; + hst_p = 0; + return SCPE_OK; + } lnt = (int32) get_uint (cptr, 10, HIST_MAX, &r); if ((r != SCPE_OK) || (lnt && (lnt < HIST_MIN))) return SCPE_ARG; hst_p = 0; if (hst_lnt) { - free (hst); - hst_lnt = 0; - hst = NULL; } + free (hst); + hst_lnt = 0; + hst = NULL; + } if (lnt) { - hst = calloc (sizeof (struct InstHistory), lnt); - if (hst == NULL) return SCPE_MEM; - hst_lnt = lnt; } + hst = (InstHistory *) calloc (lnt, sizeof (InstHistory)); + if (hst == NULL) return SCPE_MEM; + hst_lnt = lnt; + } return SCPE_OK; } @@ -1377,35 +1440,37 @@ int32 cr, k, di, op, lnt; char *cptr = (char *) desc; t_value sim_eval; t_stat r; -struct InstHistory *h; +InstHistory *h; extern t_stat fprint_sym (FILE *ofile, t_addr addr, t_value *val, - UNIT *uptr, int32 sw); + UNIT *uptr, int32 sw); static uint8 has_opnd[16] = { - 0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1 }; + 0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1 + }; -if (hst_lnt == 0) return SCPE_NOFNC; /* enabled? */ +if (hst_lnt == 0) return SCPE_NOFNC; /* enabled? */ if (cptr) { - lnt = (int32) get_uint (cptr, 10, hst_lnt, &r); - if ((r != SCPE_OK) || (lnt == 0)) return SCPE_ARG; } + lnt = (int32) get_uint (cptr, 10, hst_lnt, &r); + if ((r != SCPE_OK) || (lnt == 0)) return SCPE_ARG; + } else lnt = hst_lnt; -di = hst_p - lnt; /* work forward */ +di = hst_p - lnt; /* work forward */ if (di < 0) di = di + hst_lnt; fprintf (st, "PC C A B X ea IR\n\n"); -for (k = 0; k < lnt; k++) { /* print specified */ - h = &hst[(++di) % hst_lnt]; /* entry pointer */ - if (h->pc & HIST_PC) { /* instruction? */ - cr = (h->pc & HIST_C)? 1: 0; /* carry */ - fprintf (st, "%05o %o %06o %06o %06o ", - h->pc & X_AMASK, cr, h->ar, h->br, h->xr); - if (h->pc & HIST_EA) fprintf (st, "%05o ", h->ea); - else fprintf (st, " "); - sim_eval = h->ir; - if ((fprint_sym (st, h->pc & X_AMASK, &sim_eval, &cpu_unit, SWMASK ('M'))) > 0) - fprintf (st, "(undefined) %06o", h->ir); - op = I_GETOP (h->ir) & 017; /* base op */ - if (has_opnd[op]) fprintf (st, " [%06o]", h->opnd); - fputc ('\n', st); /* end line */ - } /* end else instruction */ - } /* end for */ +for (k = 0; k < lnt; k++) { /* print specified */ + h = &hst[(++di) % hst_lnt]; /* entry pointer */ + if (h->pc & HIST_PC) { /* instruction? */ + cr = (h->pc & HIST_C)? 1: 0; /* carry */ + fprintf (st, "%05o %o %06o %06o %06o ", + h->pc & X_AMASK, cr, h->ar, h->br, h->xr); + if (h->pc & HIST_EA) fprintf (st, "%05o ", h->ea); + else fprintf (st, " "); + sim_eval = h->ir; + if ((fprint_sym (st, h->pc & X_AMASK, &sim_eval, &cpu_unit, SWMASK ('M'))) > 0) + fprintf (st, "(undefined) %06o", h->ir); + op = I_GETOP (h->ir) & 017; /* base op */ + if (has_opnd[op]) fprintf (st, " [%06o]", h->opnd); + fputc ('\n', st); /* end line */ + } /* end else instruction */ + } /* end for */ return SCPE_OK; } diff --git a/H316/h316_defs.h b/H316/h316_defs.h index 63939ca7..510ee6ac 100644 --- a/H316/h316_defs.h +++ b/H316/h316_defs.h @@ -1,6 +1,6 @@ /* h316_defs.h: Honeywell 316/516 simulator definitions - Copyright (c) 1999-2004, Robert M. Supnik + Copyright (c) 1999-2005, 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"), @@ -19,181 +19,181 @@ 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 + 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-Feb-05 RMS Added start button interrupt - 01-Dec-04 RMS Added double precision constants - 24-Oct-03 RMS Added DMA/DMC support - 25-Apr-03 RMS Revised for extended file support + 15-Feb-05 RMS Added start button interrupt + 01-Dec-04 RMS Added double precision constants + 24-Oct-03 RMS Added DMA/DMC support + 25-Apr-03 RMS Revised for extended file support */ #ifndef _H316_DEFS_H_ -#define _H316_DEFS_H_ 0 +#define _H316_DEFS_H_ 0 -#include "sim_defs.h" /* simulator defns */ +#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_DMAER 6 /* DMA error */ -#define STOP_MTWRP 7 /* MT write protected */ -#define STOP_DPOVR 8 /* DP write overrun */ -#define STOP_DPFMT 9 /* DP invalid format */ +#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_DMAER 6 /* DMA error */ +#define STOP_MTWRP 7 /* MT write protected */ +#define STOP_DPOVR 8 /* DP write overrun */ +#define STOP_DPFMT 9 /* DP invalid format */ /* 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) +#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 DP_SIGN 010000000000 -#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 */ +#define SIGN 0100000 /* sign */ +#define DP_SIGN 010000000000 +#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_MSIZE (UNIT_V_UF + 0) /* dummy mask */ -#define UNIT_V_EXT (UNIT_V_UF + 1) /* extended mem */ -#define UNIT_V_HSA (UNIT_V_UF + 2) /* high speed arith */ -#define UNIT_V_DMC (UNIT_V_UF + 3) /* DMC */ -#define UNIT_MSIZE (1u << UNIT_V_MSIZE) -#define UNIT_EXT (1u << UNIT_V_EXT) -#define UNIT_HSA (1u << UNIT_V_HSA) -#define UNIT_DMC (1u << UNIT_V_DMC) +#define UNIT_V_MSIZE (UNIT_V_UF + 0) /* dummy mask */ +#define UNIT_V_EXT (UNIT_V_UF + 1) /* extended mem */ +#define UNIT_V_HSA (UNIT_V_UF + 2) /* high speed arith */ +#define UNIT_V_DMC (UNIT_V_UF + 3) /* DMC */ +#define UNIT_MSIZE (1u << UNIT_V_MSIZE) +#define UNIT_EXT (1u << UNIT_V_EXT) +#define UNIT_HSA (1u << UNIT_V_HSA) +#define UNIT_DMC (1u << UNIT_V_DMC) /* 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 */ - +#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 */ -#define ioEND 4 /* channel end */ +#define ioOCP 0 /* output control */ +#define ioSKS 1 /* skip if set */ +#define ioINA 2 /* input to A */ +#define ioOTA 3 /* output from A */ +#define ioEND 4 /* channel end */ /* Device information block */ struct h316_dib { - uint32 dev; /* device number */ - uint32 chan; /* dma/dmc channel */ - uint32 num; /* number of slots */ - int32 (*io) (int32 inst, int32 fnc, int32 dat, int32 dev); }; + uint32 dev; /* device number */ + uint32 chan; /* dma/dmc channel */ + uint32 num; /* number of slots */ + int32 (*io) (int32 inst, int32 fnc, int32 dat, int32 dev); }; typedef struct h316_dib DIB; /* DMA/DMC channel numbers */ -#define IOBUS 0 /* IO bus */ -#define DMA_MIN 1 /* 4 DMA channels */ -#define DMA_MAX 4 -#define DMC_MIN 1 /* 16 DMC channels */ -#define DMC_MAX 16 +#define IOBUS 0 /* IO bus */ +#define DMA_MIN 1 /* 4 DMA channels */ +#define DMA_MAX 4 +#define DMC_MIN 1 /* 16 DMC channels */ +#define DMC_MAX 16 -#define DMA1 (DMA_MIN) -#define DMC1 (DMA_MAX+DMC_MIN) +#define DMA1 (DMA_MIN) +#define DMC1 (DMA_MAX+DMC_MIN) /* DMA/DMC bit assignments in channel request word */ -#define DMA_V_DMA1 0 /* DMA channels */ -#define DMC_V_DMC1 4 /* DMC channels */ -#define SET_CH_REQ(x) chan_req = chan_req | (1 << (x)) -#define Q_DMA(x) (((x) >= 0) && ((x) < DMC_V_DMC1)) +#define DMA_V_DMA1 0 /* DMA channels */ +#define DMC_V_DMC1 4 /* DMC channels */ +#define SET_CH_REQ(x) chan_req = chan_req | (1 << (x)) +#define Q_DMA(x) (((x) >= 0) && ((x) < DMC_V_DMC1)) /* DMA/DMC definitions */ -#define DMA_IN 0100000 /* input flag */ -#define DMC_BASE 020 /* DMC memory base */ +#define DMA_IN 0100000 /* input flag */ +#define DMC_BASE 020 /* DMC memory base */ /* I/O device codes */ -#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 CLK_KEYS 020 /* clock/keys (CPU) */ -#define FHD 022 /* fixed head disk */ -#define DMA 024 /* DMA control */ -#define DP 025 /* moving head disk */ -#define DEV_MAX 64 +#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 CLK_KEYS 020 /* clock/keys (CPU) */ +#define FHD 022 /* fixed head disk */ +#define DMA 024 /* DMA control */ +#define DP 025 /* moving head disk */ +#define DEV_MAX 64 /* 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_START 16 /* start button */ -#define INT_V_NODEF 17 /* int not deferred */ -#define INT_V_ON 18 /* int on */ +#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_START 16 /* start button */ +#define INT_V_NODEF 17 /* int not deferred */ +#define INT_V_ON 18 /* 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) << IOT_V_REASON) -#define IOBADFNC(x) (((stop_inst) << IOT_V_REASON) | (x)) -#define IOSKIP(x) (IOT_SKIP | (x)) +#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) << IOT_V_REASON) +#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_START (1u << INT_V_START) -#define INT_NODEF (1u << INT_V_NODEF) -#define INT_ON (1u << INT_V_ON) -#define INT_NMI (INT_START) -#define INT_PEND (INT_ON | INT_NODEF) +#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_START (1u << INT_V_START) +#define INT_NODEF (1u << INT_V_NODEF) +#define INT_ON (1u << INT_V_ON) +#define INT_NMI (INT_START) +#define INT_PEND (INT_ON | INT_NODEF) -#define SET_INT(x) dev_int = dev_int | (x) -#define CLR_INT(x) dev_int = dev_int & ~(x) -#define TST_INT(x) ((dev_int & (x)) != 0) -#define CLR_ENB(x) dev_enb = dev_enb & ~(x) -#define TST_INTREQ(x) ((dev_int & dev_enb & (x)) != 0) +#define SET_INT(x) dev_int = dev_int | (x) +#define CLR_INT(x) dev_int = dev_int & ~(x) +#define TST_INT(x) ((dev_int & (x)) != 0) +#define CLR_ENB(x) dev_enb = dev_enb & ~(x) +#define TST_INTREQ(x) ((dev_int & dev_enb & (x)) != 0) /* Prototypes */ diff --git a/H316/h316_doc.txt b/H316/h316_doc.txt index d53462ea..604be750 100644 --- a/H316/h316_doc.txt +++ b/H316/h316_doc.txt @@ -27,8 +27,8 @@ The following copyright notice applies to both the SIMH source and binary: 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 + 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. diff --git a/H316/h316_dp.c b/H316/h316_dp.c index c8496242..a00950df 100644 --- a/H316/h316_dp.c +++ b/H316/h316_dp.c @@ -1,6 +1,6 @@ /* h316_dp.c: Honeywell 4623, 4651, 4720 disk simulator - Copyright (c) 2003-2004, Robert M. Supnik + Copyright (c) 2003-2005, 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"), @@ -19,15 +19,17 @@ 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 + 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 4623 disk subsystem - 4651 disk subsystem - 4720 disk subsystem + dp 4623 disk subsystem + 4651 disk subsystem + 4720 disk subsystem - 01-Dec-04 RMS Fixed bug in skip on !seeking + 04-Sep-05 RMS Fixed missing return (found by Peter Schorn) + 15-Jul-05 RMS Fixed bug in attach routine + 01-Dec-04 RMS Fixed bug in skip on !seeking The Honeywell disks have the unique characteristic of supporting variable formatting, on a per track basis. To accomodate this, each track is @@ -35,17 +37,17 @@ the largest record of 1891 + 8 overhead words.) A record is structured as follows: - word 0 record length n (0 = end of track) - word 1 record address (16b, uninterpreted by the simulator) - word 2 record extension (0 to 4 words of permitted 'overwrite') - word 3 first data word - : - word 3+n-1 last data word - word 3+n checksum word - word 4+n first extension word - : - word 7+n fourth extension word - word 8+n start of next record + word 0 record length n (0 = end of track) + word 1 record address (16b, uninterpreted by the simulator) + word 2 record extension (0 to 4 words of permitted 'overwrite') + word 3 first data word + : + word 3+n-1 last data word + word 3+n checksum word + word 4+n first extension word + : + word 7+n fourth extension word + word 8+n start of next record Formatting is done in two ways. The SET DPn FORMAT=k command formats unit n with k records per track, each record having the maximum allowable @@ -53,190 +55,192 @@ Alternately, the simulator allows programmatic formating. When a track is formated, the program supplies record parameters as follows: - word 0 record address - words 1-n data words - word n+1 gap size in bits + word 0 record address + words 1-n data words + word n+1 gap size in bits To make this work, the simulator tracks the consumption of bits in the track, against the track capacity in bits. Bit consumption is: - 16.5 * 16 for overhead (including address and checksum) - n * 16 for data - 'gap' for gap, which must be at least 5% of the record length + 16.5 * 16 for overhead (including address and checksum) + n * 16 for data + 'gap' for gap, which must be at least 5% of the record length */ #include "h316_defs.h" #include -#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 /* actual cylinder */ -#define UNIT_WPRT (UNIT_WLK | UNIT_RO) /* write prot */ -#define DP_TRKLEN 2048 /* track length, words */ -#define DP_NUMDRV 8 /* max # drives */ -#define DP_NUMTYP 3 /* # controller types */ +#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 /* actual cylinder */ +#define UNIT_WPRT (UNIT_WLK | UNIT_RO) /* write prot */ +#define DP_TRKLEN 2048 /* track length, words */ +#define DP_NUMDRV 8 /* max # drives */ +#define DP_NUMTYP 3 /* # controller types */ /* Record format */ -#define REC_LNT 0 /* length (unextended) */ -#define REC_ADDR 1 /* address */ -#define REC_EXT 2 /* extension (0-4) */ -#define REC_DATA 3 /* start of data */ -#define REC_OVHD 8 /* overhead words */ -#define REC_MAXEXT 4 /* maximum extension */ -#define REC_OVHD_WRDS 16.5 /* 16.5 words */ -#define REC_OVHD_BITS ((16 * 16) + 8) +#define REC_LNT 0 /* length (unextended) */ +#define REC_ADDR 1 /* address */ +#define REC_EXT 2 /* extension (0-4) */ +#define REC_DATA 3 /* start of data */ +#define REC_OVHD 8 /* overhead words */ +#define REC_MAXEXT 4 /* maximum extension */ +#define REC_OVHD_WRDS 16.5 /* 16.5 words */ +#define REC_OVHD_BITS ((16 * 16) + 8) /* Status word, ^ = dynamic */ -#define STA_BUSY 0100000 /* busy */ -#define STA_RDY 0040000 /* ready */ -#define STA_ADRER 0020000 /* address error */ -#define STA_FMTER 0010000 /* format error */ -#define STA_HNLER 0004000 /* heads not loaded (NI) */ -#define STA_OFLER 0002000 /* offline */ -#define STA_SEKER 0001000 /* seek error */ -#define STA_MBZ 0000700 -#define STA_WPRER 0000040 /* write prot error */ -#define STA_UNSER 0000020 /* unsafe */ -#define STA_CSMER 0000010 /* checksum error */ -#define STA_DTRER 0000004 /* transfer rate error */ -#define STA_ANYER 0000002 /* any error^ */ -#define STA_EOR 0000001 /* end of record */ -#define STA_ALLERR (STA_ADRER|STA_FMTER|STA_HNLER|STA_OFLER|STA_SEKER|\ - STA_WPRER|STA_UNSER|STA_DTRER) +#define STA_BUSY 0100000 /* busy */ +#define STA_RDY 0040000 /* ready */ +#define STA_ADRER 0020000 /* address error */ +#define STA_FMTER 0010000 /* format error */ +#define STA_HNLER 0004000 /* heads not loaded (NI) */ +#define STA_OFLER 0002000 /* offline */ +#define STA_SEKER 0001000 /* seek error */ +#define STA_MBZ 0000700 +#define STA_WPRER 0000040 /* write prot error */ +#define STA_UNSER 0000020 /* unsafe */ +#define STA_CSMER 0000010 /* checksum error */ +#define STA_DTRER 0000004 /* transfer rate error */ +#define STA_ANYER 0000002 /* any error^ */ +#define STA_EOR 0000001 /* end of record */ +#define STA_ALLERR (STA_ADRER|STA_FMTER|STA_HNLER|STA_OFLER|STA_SEKER|\ + STA_WPRER|STA_UNSER|STA_DTRER) /* Functions */ -#define FNC_SK0 0000 /* recalibrate */ -#define FNC_SEEK 0001 /* seek */ -#define FNC_RCA 0002 /* read current */ -#define FNC_UNL 0004 /* unload */ -#define FNC_FMT 0005 /* format */ -#define FNC_RW 0006 /* read/write */ -#define FNC_STOP 0010 /* stop format */ -#define FNC_RDS 0011 /* read status */ -#define FNC_DMA 0013 /* DMA/DMC */ -#define FNC_AKI 0014 /* acknowledge intr */ -#define FNC_IOBUS 0017 /* IO bus */ -#define FNC_2ND 0020 /* second state */ -#define FNC_3RD 0040 /* third state */ -#define FNC_4TH 0060 /* fourth state */ -#define FNC_5TH 0100 /* fifth state */ +#define FNC_SK0 0000 /* recalibrate */ +#define FNC_SEEK 0001 /* seek */ +#define FNC_RCA 0002 /* read current */ +#define FNC_UNL 0004 /* unload */ +#define FNC_FMT 0005 /* format */ +#define FNC_RW 0006 /* read/write */ +#define FNC_STOP 0010 /* stop format */ +#define FNC_RDS 0011 /* read status */ +#define FNC_DMA 0013 /* DMA/DMC */ +#define FNC_AKI 0014 /* acknowledge intr */ +#define FNC_IOBUS 0017 /* IO bus */ +#define FNC_2ND 0020 /* second state */ +#define FNC_3RD 0040 /* third state */ +#define FNC_4TH 0060 /* fourth state */ +#define FNC_5TH 0100 /* fifth state */ /* Command word 1 */ -#define CW1_RW 0100000 /* read/write */ -#define CW1_DIR 0000400 /* seek direction */ -#define CW1_V_UNIT 11 /* unit select */ -#define CW1_V_HEAD 6 /* head select */ -#define CW1_V_OFFS 0 /* seek offset */ -#define CW1_GETUNIT(x) (((x) >> CW1_V_UNIT) & dp_tab[dp_ctype].umsk) -#define CW1_GETHEAD(x) (((x) >> CW1_V_HEAD) & dp_tab[dp_ctype].hmsk) -#define CW1_GETOFFS(x) (((x) >> CW1_V_OFFS) & dp_tab[dp_ctype].cmsk) +#define CW1_RW 0100000 /* read/write */ +#define CW1_DIR 0000400 /* seek direction */ +#define CW1_V_UNIT 11 /* unit select */ +#define CW1_V_HEAD 6 /* head select */ +#define CW1_V_OFFS 0 /* seek offset */ +#define CW1_GETUNIT(x) (((x) >> CW1_V_UNIT) & dp_tab[dp_ctype].umsk) +#define CW1_GETHEAD(x) (((x) >> CW1_V_HEAD) & dp_tab[dp_ctype].hmsk) +#define CW1_GETOFFS(x) (((x) >> CW1_V_OFFS) & dp_tab[dp_ctype].cmsk) /* OTA states */ -#define OTA_NOP 0 /* normal */ -#define OTA_CW1 1 /* expecting CW1 */ -#define OTA_CW2 2 /* expecting CW2 */ +#define OTA_NOP 0 /* normal */ +#define OTA_CW1 1 /* expecting CW1 */ +#define OTA_CW2 2 /* expecting CW2 */ /* Transfer state */ -#define XIP_UMSK 007 /* unit mask */ -#define XIP_SCHED 010 /* scheduled */ -#define XIP_WRT 020 /* write */ -#define XIP_FMT 040 /* format */ - +#define XIP_UMSK 007 /* unit mask */ +#define XIP_SCHED 010 /* scheduled */ +#define XIP_WRT 020 /* write */ +#define XIP_FMT 040 /* format */ + /* The H316/516 disk emulator supports three disk controllers: - controller units cylinders surfaces data words per track + controller units cylinders surfaces data words per track - 4651 4 203 2 1908.25 - 4623 8 203 10 1816.5 - 4720 8 203 20 1908.25 + 4651 4 203 2 1908.25 + 4623 8 203 10 1816.5 + 4720 8 203 20 1908.25 Disk types may not be intermixed on the same controller. */ -#define TYPE_4651 0 -#define UNIT_4651 4 -#define CYL_4651 203 -#define SURF_4651 2 -#define WRDS_4651 1908.25 -#define UMSK_4651 0003 -#define HMSK_4651 0001 -#define CMSK_4651 0377 -#define CAP_4651 (CYL_4651*SURF_4651*DP_TRKLEN) +#define TYPE_4651 0 +#define UNIT_4651 4 +#define CYL_4651 203 +#define SURF_4651 2 +#define WRDS_4651 1908.25 +#define UMSK_4651 0003 +#define HMSK_4651 0001 +#define CMSK_4651 0377 +#define CAP_4651 (CYL_4651*SURF_4651*DP_TRKLEN) -#define TYPE_4623 1 -#define UNIT_4623 8 -#define CYL_4623 203 -#define SURF_4623 10 -#define WRDS_4623 1816.5 -#define UMSK_4623 0007 -#define HMSK_4623 0017 -#define CMSK_4623 0377 -#define CAP_4623 (CYL_4623*SURF_4623*DP_TRKLEN) +#define TYPE_4623 1 +#define UNIT_4623 8 +#define CYL_4623 203 +#define SURF_4623 10 +#define WRDS_4623 1816.5 +#define UMSK_4623 0007 +#define HMSK_4623 0017 +#define CMSK_4623 0377 +#define CAP_4623 (CYL_4623*SURF_4623*DP_TRKLEN) -#define TYPE_4720 2 -#define UNIT_4720 8 -#define CYL_4720 203 -#define SURF_4720 20 -#define WRDS_4720 1908.25 -#define UMSK_4720 0007 -#define HMSK_4720 0037 -#define CMSK_4720 0377 -#define CAP_4720 (CYL_4720*SURF_4720*DP_TRKLEN) +#define TYPE_4720 2 +#define UNIT_4720 8 +#define CYL_4720 203 +#define SURF_4720 20 +#define WRDS_4720 1908.25 +#define UMSK_4720 0007 +#define HMSK_4720 0037 +#define CMSK_4720 0377 +#define CAP_4720 (CYL_4720*SURF_4720*DP_TRKLEN) struct drvtyp { - char *name; - uint32 numu; - uint32 cyl; - uint32 surf; - uint32 cap; - uint32 umsk; - uint32 hmsk; - uint32 cmsk; - float wrds; }; + char *name; + uint32 numu; + uint32 cyl; + uint32 surf; + uint32 cap; + uint32 umsk; + uint32 hmsk; + uint32 cmsk; + float wrds; + }; #define DP_DRV(d) \ - #d, \ - UNIT_##d, CYL_##d, SURF_##d, CAP_##d, \ - UMSK_##d, HMSK_##d, CMSK_##d, WRDS_##d + #d, \ + UNIT_##d, CYL_##d, SURF_##d, CAP_##d, \ + UMSK_##d, HMSK_##d, CMSK_##d, WRDS_##d static struct drvtyp dp_tab[] = { - { DP_DRV (4651) }, - { DP_DRV (4623) }, - { DP_DRV (4720) } }; - + { DP_DRV (4651) }, + { DP_DRV (4623) }, + { DP_DRV (4720) } + }; + extern int32 dev_int, dev_enb, chan_req; extern int32 stop_inst; extern uint32 dma_ad[DMA_MAX]; extern int32 sim_switches; -uint32 dp_cw1 = 0; /* cmd word 1 */ -uint32 dp_cw2 = 0; /* cmd word 2 */ -uint32 dp_fnc = 0; /* saved function */ -uint32 dp_buf = 0; /* buffer */ -uint32 dp_otas = 0; /* state */ -uint32 dp_sta = 0; /* status */ -uint32 dp_defint = 0; /* deferred seek int */ -uint32 dp_ctype = TYPE_4651; /* controller type */ -uint32 dp_dma = 0; /* DMA/DMC */ -uint32 dp_eor = 0; /* end of range */ -uint32 dp_xip = 0; /* transfer in prog */ -uint32 dp_csum = 0; /* parity checksum */ -uint32 dp_rptr = 0; /* start of record */ -uint32 dp_wptr = 0; /* word ptr in record */ -uint32 dp_bctr = 0; /* format bit cntr */ -uint32 dp_gap = 0; /* format gap size */ -uint32 dp_stopioe = 1; /* stop on error */ -int32 dp_stime = 1000; /* seek per cylinder */ -int32 dp_xtime = 10; /* xfer per word */ -int32 dp_btime = 30; /* busy time */ -uint16 dpxb[DP_TRKLEN]; /* track buffer */ +uint32 dp_cw1 = 0; /* cmd word 1 */ +uint32 dp_cw2 = 0; /* cmd word 2 */ +uint32 dp_fnc = 0; /* saved function */ +uint32 dp_buf = 0; /* buffer */ +uint32 dp_otas = 0; /* state */ +uint32 dp_sta = 0; /* status */ +uint32 dp_defint = 0; /* deferred seek int */ +uint32 dp_ctype = TYPE_4651; /* controller type */ +uint32 dp_dma = 0; /* DMA/DMC */ +uint32 dp_eor = 0; /* end of range */ +uint32 dp_xip = 0; /* transfer in prog */ +uint32 dp_csum = 0; /* parity checksum */ +uint32 dp_rptr = 0; /* start of record */ +uint32 dp_wptr = 0; /* word ptr in record */ +uint32 dp_bctr = 0; /* format bit cntr */ +uint32 dp_gap = 0; /* format gap size */ +uint32 dp_stopioe = 1; /* stop on error */ +int32 dp_stime = 1000; /* seek per cylinder */ +int32 dp_xtime = 10; /* xfer per word */ +int32 dp_btime = 30; /* busy time */ +uint16 dpxb[DP_TRKLEN]; /* track buffer */ int32 dpio (int32 inst, int32 fnc, int32 dat, int32 dev); t_stat dp_svc (UNIT *uptr); @@ -255,213 +259,239 @@ t_stat dp_wrdone (UNIT *uptr, uint32 flg); t_stat dp_done (uint32 req, uint32 f); t_stat dp_setformat (UNIT *uptr, int32 val, char *cptr, void *desc); t_stat dp_showformat (FILE *st, UNIT *uptr, int32 val, void *desc); - + /* DP data structures - dp_dev DP device descriptor - dp_unit DP unit list - dp_reg DP register list - dp_mod DP modifier list + dp_dev DP device descriptor + dp_unit DP unit list + dp_reg DP register list + dp_mod DP modifier list */ DIB dp_dib = { DP, DMC1, 1, &dpio }; UNIT dp_unit[] = { - { UDATA (&dp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ - UNIT_ROABLE, CAP_4651) }, - { UDATA (&dp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ - UNIT_ROABLE, CAP_4651) }, - { UDATA (&dp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ - UNIT_ROABLE, CAP_4651) }, - { UDATA (&dp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ - UNIT_ROABLE, CAP_4651) }, - { UDATA (&dp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ - UNIT_ROABLE, CAP_4651) }, - { UDATA (&dp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ - UNIT_ROABLE, CAP_4651) }, - { UDATA (&dp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ - UNIT_ROABLE, CAP_4651) }, - { UDATA (&dp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ - UNIT_ROABLE, CAP_4651) } }; + { UDATA (&dp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ + UNIT_ROABLE, CAP_4651) }, + { UDATA (&dp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ + UNIT_ROABLE, CAP_4651) }, + { UDATA (&dp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ + UNIT_ROABLE, CAP_4651) }, + { UDATA (&dp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ + UNIT_ROABLE, CAP_4651) }, + { UDATA (&dp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ + UNIT_ROABLE, CAP_4651) }, + { UDATA (&dp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ + UNIT_ROABLE, CAP_4651) }, + { UDATA (&dp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ + UNIT_ROABLE, CAP_4651) }, + { UDATA (&dp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ + UNIT_ROABLE, CAP_4651) } + }; REG dp_reg[] = { - { ORDATA (STA, dp_sta, 16) }, - { ORDATA (BUF, dp_buf, 16) }, - { ORDATA (FNC, dp_fnc, 4) }, - { ORDATA (CW1, dp_cw1, 16) }, - { ORDATA (CW2, dp_cw2, 16) }, - { ORDATA (CSUM, dp_csum, 16) }, - { FLDATA (BUSY, dp_sta, 15) }, - { FLDATA (RDY, dp_sta, 14) }, - { FLDATA (EOR, dp_eor, 0) }, - { FLDATA (DEFINT, dp_defint, 0) }, - { FLDATA (INTREQ, dev_int, INT_V_DP) }, - { FLDATA (ENABLE, dev_enb, INT_V_DP) }, - { BRDATA (TBUF, dpxb, 8, 16, DP_TRKLEN) }, - { ORDATA (RPTR, dp_rptr, 11), REG_RO }, - { ORDATA (WPTR, dp_wptr, 11), REG_RO }, - { ORDATA (BCTR, dp_bctr, 15), REG_RO }, - { ORDATA (GAP, dp_gap, 16), REG_RO }, - { DRDATA (STIME, dp_stime, 24), REG_NZ + PV_LEFT }, - { DRDATA (XTIME, dp_xtime, 24), REG_NZ + PV_LEFT }, - { DRDATA (BTIME, dp_btime, 24), REG_NZ + PV_LEFT }, - { FLDATA (CTYPE, dp_ctype, 0), REG_HRO }, - { URDATA (UCYL, dp_unit[0].CYL, 10, 8, 0, - DP_NUMDRV, PV_LEFT | REG_HRO) }, - { URDATA (UFNC, dp_unit[0].FNC, 8, 7, 0, - DP_NUMDRV, REG_HRO) }, - { URDATA (CAPAC, dp_unit[0].capac, 10, T_ADDR_W, 0, - DP_NUMDRV, PV_LEFT | REG_HRO) }, - { ORDATA (OTAS, dp_otas, 2), REG_HRO }, - { ORDATA (XIP, dp_xip, 6), REG_HRO }, - { ORDATA (CHAN, dp_dib.chan, 5), REG_HRO }, - { FLDATA (STOP_IOE, dp_stopioe, 0) }, - { NULL } }; + { ORDATA (STA, dp_sta, 16) }, + { ORDATA (BUF, dp_buf, 16) }, + { ORDATA (FNC, dp_fnc, 4) }, + { ORDATA (CW1, dp_cw1, 16) }, + { ORDATA (CW2, dp_cw2, 16) }, + { ORDATA (CSUM, dp_csum, 16) }, + { FLDATA (BUSY, dp_sta, 15) }, + { FLDATA (RDY, dp_sta, 14) }, + { FLDATA (EOR, dp_eor, 0) }, + { FLDATA (DEFINT, dp_defint, 0) }, + { FLDATA (INTREQ, dev_int, INT_V_DP) }, + { FLDATA (ENABLE, dev_enb, INT_V_DP) }, + { BRDATA (TBUF, dpxb, 8, 16, DP_TRKLEN) }, + { ORDATA (RPTR, dp_rptr, 11), REG_RO }, + { ORDATA (WPTR, dp_wptr, 11), REG_RO }, + { ORDATA (BCTR, dp_bctr, 15), REG_RO }, + { ORDATA (GAP, dp_gap, 16), REG_RO }, + { DRDATA (STIME, dp_stime, 24), REG_NZ + PV_LEFT }, + { DRDATA (XTIME, dp_xtime, 24), REG_NZ + PV_LEFT }, + { DRDATA (BTIME, dp_btime, 24), REG_NZ + PV_LEFT }, + { FLDATA (CTYPE, dp_ctype, 0), REG_HRO }, + { URDATA (UCYL, dp_unit[0].CYL, 10, 8, 0, + DP_NUMDRV, PV_LEFT | REG_HRO) }, + { URDATA (UFNC, dp_unit[0].FNC, 8, 7, 0, + DP_NUMDRV, REG_HRO) }, + { URDATA (CAPAC, dp_unit[0].capac, 10, T_ADDR_W, 0, + DP_NUMDRV, PV_LEFT | REG_HRO) }, + { ORDATA (OTAS, dp_otas, 2), REG_HRO }, + { ORDATA (XIP, dp_xip, 6), REG_HRO }, + { ORDATA (CHAN, dp_dib.chan, 5), REG_HRO }, + { FLDATA (STOP_IOE, dp_stopioe, 0) }, + { NULL } + }; MTAB dp_mod[] = { - { UNIT_WLK, 0, "write enabled", "WRITEENABLED", NULL }, - { UNIT_WLK, UNIT_WLK, "write locked", "LOCKED", NULL }, - { MTAB_XTD | MTAB_VDV, TYPE_4623, NULL, "4623", - &dp_settype, NULL, NULL }, - { MTAB_XTD | MTAB_VDV, TYPE_4651, NULL, "4651", - &dp_settype, NULL, NULL }, - { MTAB_XTD | MTAB_VDV, TYPE_4720, NULL, "4720", - &dp_settype, NULL, NULL }, - { MTAB_XTD | MTAB_VDV, 0, "TYPE", NULL, - NULL, &dp_showtype, NULL }, - { MTAB_XTD|MTAB_VDV, 0, NULL, "DMC", - &io_set_dmc, NULL, NULL }, - { MTAB_XTD|MTAB_VDV, 0, NULL, "DMA", - &io_set_dma, NULL, NULL }, - { MTAB_XTD|MTAB_VDV, 0, "CHANNEL", NULL, - NULL, &io_show_chan, NULL }, - { MTAB_XTD|MTAB_VUN|MTAB_NMO, 0, "FORMAT", "FORMAT", - &dp_setformat, &dp_showformat, NULL }, - { 0 } }; + { UNIT_WLK, 0, "write enabled", "WRITEENABLED", NULL }, + { UNIT_WLK, UNIT_WLK, "write locked", "LOCKED", NULL }, + { MTAB_XTD | MTAB_VDV, TYPE_4623, NULL, "4623", + &dp_settype, NULL, NULL }, + { MTAB_XTD | MTAB_VDV, TYPE_4651, NULL, "4651", + &dp_settype, NULL, NULL }, + { MTAB_XTD | MTAB_VDV, TYPE_4720, NULL, "4720", + &dp_settype, NULL, NULL }, + { MTAB_XTD | MTAB_VDV, 0, "TYPE", NULL, + NULL, &dp_showtype, NULL }, + { MTAB_XTD|MTAB_VDV, 0, NULL, "DMC", + &io_set_dmc, NULL, NULL }, + { MTAB_XTD|MTAB_VDV, 0, NULL, "DMA", + &io_set_dma, NULL, NULL }, + { MTAB_XTD|MTAB_VDV, 0, "CHANNEL", NULL, + NULL, &io_show_chan, NULL }, + { MTAB_XTD|MTAB_VUN|MTAB_NMO, 0, "FORMAT", "FORMAT", + &dp_setformat, &dp_showformat, NULL }, + { 0 } + }; DEVICE dp_dev = { - "DP", dp_unit, dp_reg, dp_mod, - DP_NUMDRV, 8, 24, 1, 8, 16, - NULL, NULL, &dp_reset, - NULL, &dp_attach, NULL, - &dp_dib, DEV_DISABLE }; - + "DP", dp_unit, dp_reg, dp_mod, + DP_NUMDRV, 8, 24, 1, 8, 16, + NULL, NULL, &dp_reset, + NULL, &dp_attach, NULL, + &dp_dib, DEV_DISABLE + }; + /* IOT routines */ int32 dpio (int32 inst, int32 fnc, int32 dat, int32 dev) { -int32 ch = dp_dib.chan - 1; /* DMA/DMC chan */ +int32 ch = dp_dib.chan - 1; /* DMA/DMC chan */ int32 u; UNIT *uptr; -switch (inst) { /* case on opcode */ -case ioOCP: /* OCP */ - switch (fnc) { /* case on function */ - case FNC_SK0: case FNC_SEEK: case FNC_RCA: /* data transfer */ - case FNC_UNL: case FNC_FMT: case FNC_RW: - dp_go (fnc); /* if !busy, start */ - break; - case FNC_STOP: /* stop transfer */ - if (dp_xip) { /* transfer in prog? */ - uptr = dp_dev.units + (dp_xip & XIP_UMSK); /* get unit */ - sim_cancel (uptr); /* stop operation */ - if (dp_xip & (XIP_WRT|XIP_FMT)) /* write or format? */ - dp_wrdone (uptr, /* write track */ - ((dp_xip & XIP_FMT) && /* check fmt state */ - (uptr->FNC != (FNC_FMT|FNC_2ND)))? - STA_DTRER: 0); - else dp_done (1, dp_csum? STA_CSMER: 0);/* no, just clr busy */ - dp_xip = 0; } /* clear flag */ - dp_otas = OTA_NOP; /* clear state */ - dp_sta = dp_sta & ~STA_BUSY; /* clear busy */ - break; - case FNC_RDS: /* read status */ - if (dp_sta & STA_BUSY) return dat; /* ignore if busy */ - dp_sta = (dp_sta | STA_RDY) & ~(STA_MBZ | STA_ANYER); - if (dp_sta & STA_ALLERR) dp_sta = dp_sta | STA_ANYER; - dp_buf = dp_sta; - if (dp_dma && Q_DMA (ch)) SET_CH_REQ (ch); /* DMA? set chan req */ - break; - case FNC_DMA: /* set DMA/DMC */ - dp_dma = 1; - break; - case FNC_IOBUS: /* set IO bus */ - dp_dma = 0; - break; - case FNC_AKI: /* ack intr */ - CLR_INT (INT_DP); - break; - default: /* undefined */ - return IOBADFNC (dat); } - break; +switch (inst) { /* case on opcode */ + case ioOCP: /* OCP */ + switch (fnc) { /* case on function */ -case ioINA: /* INA */ - if (fnc) return IOBADFNC (dat); /* fnc 0 only */ - if (dp_sta & STA_RDY) { /* ready? */ - dp_sta = dp_sta & ~STA_RDY; /* clear ready */ - return IOSKIP (dat | dp_buf); } /* ret buf, skip */ - break; + case FNC_SK0: case FNC_SEEK: case FNC_RCA: /* data transfer */ + case FNC_UNL: case FNC_FMT: case FNC_RW: + dp_go (fnc); /* if !busy, start */ + break; + + case FNC_STOP: /* stop transfer */ + if (dp_xip) { /* transfer in prog? */ + uptr = dp_dev.units + (dp_xip & XIP_UMSK); /* get unit */ + sim_cancel (uptr); /* stop operation */ + if (dp_xip & (XIP_WRT|XIP_FMT)) /* write or format? */ + dp_wrdone (uptr, /* write track */ + ((dp_xip & XIP_FMT) && /* check fmt state */ + (uptr->FNC != (FNC_FMT|FNC_2ND)))? + STA_DTRER: 0); + else dp_done (1, dp_csum? STA_CSMER: 0);/* no, just clr busy */ + dp_xip = 0; /* clear flag */ + } + dp_otas = OTA_NOP; /* clear state */ + dp_sta = dp_sta & ~STA_BUSY; /* clear busy */ + break; + + case FNC_RDS: /* read status */ + if (dp_sta & STA_BUSY) return dat; /* ignore if busy */ + dp_sta = (dp_sta | STA_RDY) & ~(STA_MBZ | STA_ANYER); + if (dp_sta & STA_ALLERR) dp_sta = dp_sta | STA_ANYER; + dp_buf = dp_sta; + if (dp_dma && Q_DMA (ch)) SET_CH_REQ (ch); /* DMA? set chan req */ + break; + + case FNC_DMA: /* set DMA/DMC */ + dp_dma = 1; + break; + + case FNC_IOBUS: /* set IO bus */ + dp_dma = 0; + break; + + case FNC_AKI: /* ack intr */ + CLR_INT (INT_DP); + break; + + default: /* undefined */ + return IOBADFNC (dat); + } + break; + + case ioINA: /* INA */ + if (fnc) return IOBADFNC (dat); /* fnc 0 only */ + if (dp_sta & STA_RDY) { /* ready? */ + dp_sta = dp_sta & ~STA_RDY; /* clear ready */ + return IOSKIP (dat | dp_buf); /* ret buf, skip */ + } + break; + + case ioOTA: /* OTA */ + if (fnc) return IOBADFNC (dat); /* fnc 0 only */ + if (dp_sta & STA_RDY) { /* ready? */ + dp_sta = dp_sta & ~STA_RDY; /* clear ready */ + dp_buf = dat; /* store buf */ + if (dp_otas == OTA_CW1) dp_go1 (dat); /* expecting CW1? */ + else if (dp_otas == OTA_CW2) dp_go2 (dat); /* expecting CW2? */ + return IOSKIP (dat); + } + break; + + case ioSKS: /* SKS */ + u = 7; /* assume unit 7 */ + switch (fnc) { + + case 000: /* ready */ + if (dp_sta & STA_RDY) return IOSKIP (dat); + break; + + case 001: /* !interrupting */ + if (!TST_INTREQ (INT_DP)) return IOSKIP (dat); + break; + + case 002: /* operational */ + if (!(dp_sta & (STA_BUSY | STA_ALLERR))) return IOSKIP (dat); + break; + + case 003: /* !error */ + if (!(dp_sta & STA_ALLERR)) return IOSKIP (dat); + break; + + case 004: /* !busy */ + if (!(dp_sta & STA_BUSY)) return IOSKIP (dat); + break; + + case 011: case 012: case 013: /* !not seeking 0-6 */ + case 014: case 015: case 016: case 017: + u = fnc - 011; + case 007: /* !not seeking 7 */ + if (!sim_is_active (&dp_unit[u]) || /* quiescent? */ + (dp_unit[u].FNC != (FNC_SEEK | FNC_2ND))) + return IOSKIP (dat); /* seeking sets late */ + break; + } + break; + + case ioEND: /* end of range */ + dp_eor = 1; /* transfer done */ + break; + } -case ioOTA: /* OTA */ - if (fnc) return IOBADFNC (dat); /* fnc 0 only */ - if (dp_sta & STA_RDY) { /* ready? */ - dp_sta = dp_sta & ~STA_RDY; /* clear ready */ - dp_buf = dat; /* store buf */ - if (dp_otas == OTA_CW1) dp_go1 (dat); /* expecting CW1? */ - else if (dp_otas == OTA_CW2) dp_go2 (dat); /* expecting CW2? */ - return IOSKIP (dat); } - break; -case ioSKS: /* SKS */ - u = 7; /* assume unit 7 */ - switch (fnc) { - case 000: /* ready */ - if (dp_sta & STA_RDY) return IOSKIP (dat); - break; - case 001: /* !interrupting */ - if (!TST_INTREQ (INT_DP)) return IOSKIP (dat); - break; - case 002: /* operational */ - if (!(dp_sta & (STA_BUSY | STA_ALLERR))) return IOSKIP (dat); - break; - case 003: /* !error */ - if (!(dp_sta & STA_ALLERR)) return IOSKIP (dat); - break; - case 004: /* !busy */ - if (!(dp_sta & STA_BUSY)) return IOSKIP (dat); - break; - case 011: case 012: case 013: /* !not seeking 0-6 */ - case 014: case 015: case 016: case 017: - u = fnc - 011; - case 007: /* !not seeking 7 */ - if (!sim_is_active (&dp_unit[u]) || /* quiescent? */ - (dp_unit[u].FNC != (FNC_SEEK | FNC_2ND))) - return IOSKIP (dat); /* seeking sets late */ - break; } - break; -case ioEND: /* end of range */ - dp_eor = 1; /* transfer done */ - break; } return dat; } - /* Start new operation - recal, seek, read address, format, read/write */ t_stat dp_go (uint32 fnc) { -int32 ch = dp_dib.chan - 1; /* DMA/DMC chan */ +int32 ch = dp_dib.chan - 1; /* DMA/DMC chan */ -if (dp_sta & STA_BUSY) return SCPE_OK; /* ignore if busy */ -dp_fnc = fnc; /* save function */ -dp_xip = 0; /* transfer not started */ -dp_eor = 0; /* not end of range */ -dp_csum = 0; /* init checksum */ -dp_otas = OTA_CW1; /* expect CW1 */ +if (dp_sta & STA_BUSY) return SCPE_OK; /* ignore if busy */ +dp_fnc = fnc; /* save function */ +dp_xip = 0; /* transfer not started */ +dp_eor = 0; /* not end of range */ +dp_csum = 0; /* init checksum */ +dp_otas = OTA_CW1; /* expect CW1 */ dp_sta = (dp_sta | STA_BUSY | STA_RDY) & ~(STA_ALLERR | STA_EOR); -if (dp_dma && Q_DMA (ch)) { /* DMA and DMA channel? */ - SET_CH_REQ (ch); /* set channel request */ - dma_ad[ch] = dma_ad[ch] & ~DMA_IN; } /* force output */ +if (dp_dma && Q_DMA (ch)) { /* DMA and DMA channel? */ + SET_CH_REQ (ch); /* set channel request */ + dma_ad[ch] = dma_ad[ch] & ~DMA_IN; /* force output */ + } return SCPE_OK; } @@ -469,35 +499,41 @@ return SCPE_OK; t_stat dp_go1 (uint32 dat) { -int32 ch = dp_dib.chan - 1; /* DMA/DMC chan */ +int32 ch = dp_dib.chan - 1; /* DMA/DMC chan */ uint32 u = CW1_GETUNIT (dat); UNIT *uptr = dp_dev.units + u; -dp_cw1 = dat; /* store CW1 */ -dp_otas = OTA_NOP; /* assume no CW2 */ +dp_cw1 = dat; /* store CW1 */ +dp_otas = OTA_NOP; /* assume no CW2 */ uptr->FNC = dp_fnc; -if (sim_is_active (uptr)) /* still seeking? */ - return dp_done (1, STA_UNSER); /* unsafe */ -if (!(uptr->flags & UNIT_ATT)) /* not attached? */ - return dp_done (1, STA_OFLER); /* offline */ -switch (dp_fnc) { /* case on function */ -case FNC_SEEK: /* seek */ -case FNC_SK0: /* recalibrate */ -case FNC_UNL: /* unload */ - sim_activate (uptr, dp_btime); /* quick timeout */ - break; -case FNC_FMT: /* format */ - if (uptr->flags & UNIT_WPRT) /* write protect? */ - return dp_done (1, STA_WPRER); /* stop now */ -case FNC_RCA: /* read current addr */ - dp_xip = u | XIP_SCHED; /* operation started */ - sim_activate (uptr, dp_xtime * 10); /* rotation timeout */ - break; -case FNC_RW: /* read/write */ - dp_otas = OTA_CW2; /* expect CW2 */ - dp_sta = dp_sta | STA_RDY; /* set ready */ - if (dp_dma && Q_DMA (ch)) SET_CH_REQ (ch); /* DMA? set chan request */ - break; } +if (sim_is_active (uptr)) /* still seeking? */ + return dp_done (1, STA_UNSER); /* unsafe */ +if (!(uptr->flags & UNIT_ATT)) /* not attached? */ + return dp_done (1, STA_OFLER); /* offline */ + +switch (dp_fnc) { /* case on function */ + + case FNC_SEEK: /* seek */ + case FNC_SK0: /* recalibrate */ + case FNC_UNL: /* unload */ + sim_activate (uptr, dp_btime); /* quick timeout */ + break; + + case FNC_FMT: /* format */ + if (uptr->flags & UNIT_WPRT) /* write protect? */ + return dp_done (1, STA_WPRER); /* stop now */ + case FNC_RCA: /* read current addr */ + dp_xip = u | XIP_SCHED; /* operation started */ + sim_activate (uptr, dp_xtime * 10); /* rotation timeout */ + break; + + case FNC_RW: /* read/write */ + dp_otas = OTA_CW2; /* expect CW2 */ + dp_sta = dp_sta | STA_RDY; /* set ready */ + if (dp_dma && Q_DMA (ch)) SET_CH_REQ (ch); /* DMA? set chan request */ + break; + } + return SCPE_OK; } @@ -508,73 +544,77 @@ t_stat dp_go2 (uint32 dat) uint32 u = CW1_GETUNIT (dp_cw1); UNIT *uptr = dp_dev.units + u; -dp_cw2 = dat; /* store CW2 */ -dp_otas = OTA_NOP; /* normal state */ -sim_activate (uptr, dp_xtime * 10); /* rotation timeout */ -dp_xip = u | XIP_SCHED; /* operation started */ +dp_cw2 = dat; /* store CW2 */ +dp_otas = OTA_NOP; /* normal state */ +sim_activate (uptr, dp_xtime * 10); /* rotation timeout */ +dp_xip = u | XIP_SCHED; /* operation started */ return SCPE_OK; } - + /* Unit service */ t_stat dp_svc (UNIT *uptr) { -int32 dcyl = 0; /* assume recalibrate */ -int32 ch = dp_dib.chan - 1; /* DMA/DMC chan */ -uint32 h = CW1_GETHEAD (dp_cw1); /* head */ +int32 dcyl = 0; /* assume recalibrate */ +int32 ch = dp_dib.chan - 1; /* DMA/DMC chan */ +uint32 h = CW1_GETHEAD (dp_cw1); /* head */ int32 st; uint32 i, offs, lnt, ming, tpos; t_stat r; -if (!(uptr->flags & UNIT_ATT)) { /* not attached? */ - dp_done (1, STA_OFLER); /* offline */ - IORETURN (dp_stopioe, SCPE_UNATT); } +if (!(uptr->flags & UNIT_ATT)) { /* not attached? */ + dp_done (1, STA_OFLER); /* offline */ + return IORETURN (dp_stopioe, SCPE_UNATT); + } -switch (uptr->FNC) { /* case on function */ -case FNC_SEEK: /* seek, need cyl */ - offs = CW1_GETOFFS (dp_cw1); /* get offset */ - if (dp_cw1 & CW1_DIR) dcyl = uptr->CYL - offs; /* get desired cyl */ - else dcyl = uptr->CYL + offs; - if ((offs == 0) || (dcyl < 0) || - (dcyl >= (int32) dp_tab[dp_ctype].cyl)) - return dp_done (1, STA_SEKER); /* bad seek? */ -case FNC_SK0: /* recalibrate */ - dp_sta = dp_sta & ~STA_BUSY; /* clear busy */ - uptr->FNC = FNC_SEEK | FNC_2ND; /* next state */ - st = (abs (dcyl - uptr->CYL)) * dp_stime; /* schedule seek */ - if (st == 0) st = dp_stime; - uptr->CYL = dcyl; /* put on cylinder */ - sim_activate (uptr, st); - return SCPE_OK; +switch (uptr->FNC) { /* case on function */ -case FNC_SEEK | FNC_2ND: /* seek, 2nd state */ - if (dp_sta & STA_BUSY) dp_defint = 1; /* busy? queue intr */ - else SET_INT (INT_DP); /* no, req intr */ - return SCPE_OK; + case FNC_SEEK: /* seek, need cyl */ + offs = CW1_GETOFFS (dp_cw1); /* get offset */ + if (dp_cw1 & CW1_DIR) dcyl = uptr->CYL - offs; /* get desired cyl */ + else dcyl = uptr->CYL + offs; + if ((offs == 0) || (dcyl < 0) || + (dcyl >= (int32) dp_tab[dp_ctype].cyl)) + return dp_done (1, STA_SEKER); /* bad seek? */ -case FNC_UNL: /* unload */ - detach_unit (uptr); /* detach unit */ - return dp_done (0, 0); /* clear busy, no intr */ + case FNC_SK0: /* recalibrate */ + dp_sta = dp_sta & ~STA_BUSY; /* clear busy */ + uptr->FNC = FNC_SEEK | FNC_2ND; /* next state */ + st = (abs (dcyl - uptr->CYL)) * dp_stime; /* schedule seek */ + if (st == 0) st = dp_stime; + uptr->CYL = dcyl; /* put on cylinder */ + sim_activate (uptr, st); + return SCPE_OK; + + case FNC_SEEK | FNC_2ND: /* seek, 2nd state */ + if (dp_sta & STA_BUSY) dp_defint = 1; /* busy? queue intr */ + else SET_INT (INT_DP); /* no, req intr */ + return SCPE_OK; + + case FNC_UNL: /* unload */ + detach_unit (uptr); /* detach unit */ + return dp_done (0, 0); /* clear busy, no intr */ + + case FNC_RCA: /* read current addr */ + if (h >= dp_tab[dp_ctype].surf) /* invalid head? */ + return dp_done (1, STA_ADRER); /* error */ + if (r = dp_rdtrk (uptr, dpxb, uptr->CYL, h)) /* get track; error? */ + return r; + dp_rptr = 0; /* init rec ptr */ + if (dpxb[dp_rptr + REC_LNT] == 0) /* unformated? */ + return dp_done (1, STA_ADRER); /* error */ + tpos = (uint32) (fmod (sim_gtime () / (double) dp_xtime, DP_TRKLEN)); + do { /* scan down track */ + dp_buf = dpxb[dp_rptr + REC_ADDR]; /* get rec addr */ + dp_rptr = dp_rptr + dpxb[dp_rptr + REC_LNT] + REC_OVHD; + } while ((dp_rptr < tpos) && (dpxb[dp_rptr + REC_LNT] != 0)); + if (dp_dma) { /* DMA/DMC? */ + if (Q_DMA (ch)) /* DMA? */ + dma_ad[ch] = dma_ad[ch] | DMA_IN; /* force input */ + SET_CH_REQ (ch); /* request chan */ + } + return dp_done (1, STA_RDY); /* clr busy, set rdy */ -case FNC_RCA: /* read current addr */ - if (h >= dp_tab[dp_ctype].surf) /* invalid head? */ - return dp_done (1, STA_ADRER); /* error */ - if (r = dp_rdtrk (uptr, dpxb, uptr->CYL, h)) /* get track; error? */ - return r; - dp_rptr = 0; /* init rec ptr */ - if (dpxb[dp_rptr + REC_LNT] == 0) /* unformated? */ - return dp_done (1, STA_ADRER); /* error */ - tpos = (uint32) (fmod (sim_gtime () / (double) dp_xtime, DP_TRKLEN)); - do { /* scan down track */ - dp_buf = dpxb[dp_rptr + REC_ADDR]; /* get rec addr */ - dp_rptr = dp_rptr + dpxb[dp_rptr + REC_LNT] + REC_OVHD; } - while ((dp_rptr < tpos) && (dpxb[dp_rptr + REC_LNT] != 0)); - if (dp_dma) { /* DMA/DMC? */ - if (Q_DMA (ch)) /* DMA? */ - dma_ad[ch] = dma_ad[ch] | DMA_IN; /* force input */ - SET_CH_REQ (ch); } /* request chan */ - return dp_done (1, STA_RDY); /* clr busy, set rdy */ - /* Formating takes place in five states: init - clear track buffer, start at first record @@ -588,64 +628,68 @@ case FNC_RCA: /* read current addr */ in the proper state (gap word received), a format error occurs. */ -case FNC_FMT: /* format */ - for (i = 0; i < DP_TRKLEN; i++) dpxb[i] = 0; /* clear track */ - dp_xip = dp_xip | XIP_FMT; /* format in progress */ - dp_rptr = 0; /* init record ptr */ - dp_gap = 0; /* no gap before first */ - dp_bctr = (uint32) (16.0 * dp_tab[dp_ctype].wrds); /* init bit cntr */ - uptr->FNC = uptr->FNC | FNC_2ND; /* address state */ - break; /* set up next word */ + case FNC_FMT: /* format */ + for (i = 0; i < DP_TRKLEN; i++) dpxb[i] = 0; /* clear track */ + dp_xip = dp_xip | XIP_FMT; /* format in progress */ + dp_rptr = 0; /* init record ptr */ + dp_gap = 0; /* no gap before first */ + dp_bctr = (uint32) (16.0 * dp_tab[dp_ctype].wrds); /* init bit cntr */ + uptr->FNC = uptr->FNC | FNC_2ND; /* address state */ + break; /* set up next word */ -case FNC_FMT | FNC_2ND: /* format, address word */ - dp_wptr = 0; /* clear word ptr */ - if (dp_bctr < (dp_gap + REC_OVHD_BITS + 16)) /* room for gap, record? */ - return dp_wrdone (uptr, STA_FMTER); /* no, format error */ - dp_bctr = dp_bctr - dp_gap - REC_OVHD_BITS; /* charge for gap, ovhd */ - dpxb[dp_rptr + REC_ADDR] = dp_buf; /* store address */ - uptr->FNC = FNC_FMT | FNC_3RD; /* data state */ - if (dp_eor) { /* record done? */ - dp_eor = 0; /* clear for restart */ - if (dp_dma) SET_INT (INT_DP); } /* DMA/DMC? intr */ - break; /* set up next word */ + case FNC_FMT | FNC_2ND: /* format, address word */ + dp_wptr = 0; /* clear word ptr */ + if (dp_bctr < (dp_gap + REC_OVHD_BITS + 16)) /* room for gap, record? */ + return dp_wrdone (uptr, STA_FMTER); /* no, format error */ + dp_bctr = dp_bctr - dp_gap - REC_OVHD_BITS; /* charge for gap, ovhd */ + dpxb[dp_rptr + REC_ADDR] = dp_buf; /* store address */ + uptr->FNC = FNC_FMT | FNC_3RD; /* data state */ + if (dp_eor) { /* record done? */ + dp_eor = 0; /* clear for restart */ + if (dp_dma) SET_INT (INT_DP); /* DMA/DMC? intr */ + } + break; /* set up next word */ -case FNC_FMT | FNC_3RD: /* format, data word */ - if (dp_sta & STA_RDY) /* timing failure? */ - return dp_wrdone (uptr, STA_DTRER); /* write trk, err */ - else { /* no, have word */ - if (dp_bctr < 16) /* room for it? */ - return dp_wrdone (uptr, STA_FMTER); /* no, error */ - dp_bctr = dp_bctr - 16; /* charge for word */ - dp_csum = dp_csum ^ dp_buf; /* update checksum */ - dpxb[dp_rptr + REC_DATA + dp_wptr] = dp_buf;/* store word */ - dpxb[dp_rptr + REC_LNT]++; /* incr rec lnt */ - dp_wptr++; } /* incr word ptr */ - if (dp_eor) { /* record done? */ - dp_eor = 0; /* clear for restart */ - if (dp_dma) SET_INT (INT_DP); /* DMA/DMC? intr */ - dpxb[dp_rptr + REC_DATA + dp_wptr] = dp_csum; /* store checksum */ - uptr->FNC = uptr->FNC | FNC_4TH; /* pause state */ - sim_activate (uptr, 5 * dp_xtime); /* schedule pause */ - return SCPE_OK; } /* don't request word */ - break; /* set up next word */ + case FNC_FMT | FNC_3RD: /* format, data word */ + if (dp_sta & STA_RDY) /* timing failure? */ + return dp_wrdone (uptr, STA_DTRER); /* write trk, err */ + else { /* no, have word */ + if (dp_bctr < 16) /* room for it? */ + return dp_wrdone (uptr, STA_FMTER); /* no, error */ + dp_bctr = dp_bctr - 16; /* charge for word */ + dp_csum = dp_csum ^ dp_buf; /* update checksum */ + dpxb[dp_rptr + REC_DATA + dp_wptr] = dp_buf;/* store word */ + dpxb[dp_rptr + REC_LNT]++; /* incr rec lnt */ + dp_wptr++; /* incr word ptr */ + } + if (dp_eor) { /* record done? */ + dp_eor = 0; /* clear for restart */ + if (dp_dma) SET_INT (INT_DP); /* DMA/DMC? intr */ + dpxb[dp_rptr + REC_DATA + dp_wptr] = dp_csum; /* store checksum */ + uptr->FNC = uptr->FNC | FNC_4TH; /* pause state */ + sim_activate (uptr, 5 * dp_xtime); /* schedule pause */ + return SCPE_OK; /* don't request word */ + } + break; /* set up next word */ -case FNC_FMT | FNC_4TH: /* format, pause */ - uptr->FNC = FNC_FMT | FNC_5TH; /* gap state */ - break; /* request word */ + case FNC_FMT | FNC_4TH: /* format, pause */ + uptr->FNC = FNC_FMT | FNC_5TH; /* gap state */ + break; /* request word */ + + case FNC_FMT | FNC_5TH: /* format, gap word */ + ming = ((16 * dp_wptr) + REC_OVHD_BITS) / 20; /* min 5% gap */ + if (dp_buf < ming) /* too small? */ + return dp_wrdone (uptr, STA_FMTER); /* yes, format error */ + dp_rptr = dp_rptr + dp_wptr + REC_OVHD; /* next record */ + uptr->FNC = FNC_FMT | FNC_2ND; /* address state */ + if (dp_eor) { /* record done? */ + dp_eor = 0; /* clear for restart */ + if (dp_dma) SET_INT (INT_DP); /* DMA/DMC? intr */ + } + dp_gap = dp_buf; /* save gap */ + dp_csum = 0; /* clear checksum */ + break; /* set up next word */ -case FNC_FMT | FNC_5TH: /* format, gap word */ - ming = ((16 * dp_wptr) + REC_OVHD_BITS) / 20; /* min 5% gap */ - if (dp_buf < ming) /* too small? */ - return dp_wrdone (uptr, STA_FMTER); /* yes, format error */ - dp_rptr = dp_rptr + dp_wptr + REC_OVHD; /* next record */ - uptr->FNC = FNC_FMT | FNC_2ND; /* address state */ - if (dp_eor) { /* record done? */ - dp_eor = 0; /* clear for restart */ - if (dp_dma) SET_INT (INT_DP); } /* DMA/DMC? intr */ - dp_gap = dp_buf; /* save gap */ - dp_csum = 0; /* clear checksum */ - break; /* set up next word */ - /* Read and write take place in two states: init - read track into buffer, find record, validate parameters @@ -653,60 +697,66 @@ case FNC_FMT | FNC_5TH: /* format, gap word */ - (write) write data into buffer, flush on end of range */ -case FNC_RW: /* read/write */ - if (h >= dp_tab[dp_ctype].surf) /* invalid head? */ - return dp_done (1, STA_ADRER); /* error */ - if (r = dp_rdtrk (uptr, dpxb, uptr->CYL, h)) /* get track; error? */ - return r; - if (!dp_findrec (dp_cw2)) /* find rec; error? */ - return dp_done (1, STA_ADRER); /* address error */ - if ((dpxb[dp_rptr + REC_LNT] >= (DP_TRKLEN - dp_rptr - REC_OVHD)) || - (dpxb[dp_rptr + REC_EXT] >= REC_MAXEXT)) { /* bad lnt or ext? */ - dp_done (1, STA_UNSER); /* stop simulation */ - return STOP_DPFMT; } /* bad format */ - uptr->FNC = uptr->FNC | FNC_2ND; /* next state */ - if (dp_cw1 & CW1_RW) { /* write? */ - if (uptr->flags & UNIT_WPRT) /* write protect? */ - return dp_done (1, STA_WPRER); /* error */ - dp_xip = dp_xip | XIP_WRT; /* write in progress */ - dp_sta = dp_sta | STA_RDY; /* set ready */ - if (dp_dma) SET_CH_REQ (ch); } /* if DMA/DMC, req chan */ - else if (Q_DMA (ch)) /* read; DMA? */ - dma_ad[ch] = dma_ad[ch] | DMA_IN; /* force input */ - sim_activate (uptr, dp_xtime); /* schedule word */ - dp_wptr = 0; /* init word pointer */ - return SCPE_OK; + case FNC_RW: /* read/write */ + if (h >= dp_tab[dp_ctype].surf) /* invalid head? */ + return dp_done (1, STA_ADRER); /* error */ + if (r = dp_rdtrk (uptr, dpxb, uptr->CYL, h)) /* get track; error? */ + return r; + if (!dp_findrec (dp_cw2)) /* find rec; error? */ + return dp_done (1, STA_ADRER); /* address error */ + if ((dpxb[dp_rptr + REC_LNT] >= (DP_TRKLEN - dp_rptr - REC_OVHD)) || + (dpxb[dp_rptr + REC_EXT] >= REC_MAXEXT)) { /* bad lnt or ext? */ + dp_done (1, STA_UNSER); /* stop simulation */ + return STOP_DPFMT; /* bad format */ + } + uptr->FNC = uptr->FNC | FNC_2ND; /* next state */ + if (dp_cw1 & CW1_RW) { /* write? */ + if (uptr->flags & UNIT_WPRT) /* write protect? */ + return dp_done (1, STA_WPRER); /* error */ + dp_xip = dp_xip | XIP_WRT; /* write in progress */ + dp_sta = dp_sta | STA_RDY; /* set ready */ + if (dp_dma) SET_CH_REQ (ch); /* if DMA/DMC, req chan */ + } + else if (Q_DMA (ch)) /* read; DMA? */ + dma_ad[ch] = dma_ad[ch] | DMA_IN; /* force input */ + sim_activate (uptr, dp_xtime); /* schedule word */ + dp_wptr = 0; /* init word pointer */ + return SCPE_OK; -case FNC_RW | FNC_2ND: /* read/write, word */ - if (dp_cw1 & CW1_RW) { /* write? */ - if (dp_sta & STA_RDY) /* timing failure? */ - return dp_wrdone (uptr, STA_DTRER); /* yes, error */ - if (r = dp_wrwd (uptr, dp_buf)) return r; /* wr word, error? */ - if (dp_eor) { /* transfer done? */ - dpxb[dp_rptr + REC_DATA + dp_wptr] = dp_csum; - return dp_wrdone (uptr, 0); } } /* clear busy, intr req */ - else { /* read? */ - lnt = dpxb[dp_rptr + REC_LNT] + dpxb[dp_rptr + REC_EXT]; - dp_buf = dpxb[dp_rptr + REC_DATA + dp_wptr];/* current word */ - dp_csum = dp_csum ^ dp_buf; /* xor to csum */ - if ((dp_wptr > lnt) || dp_eor) /* transfer done? */ - return dp_done (1, - (dp_csum? STA_CSMER: 0) | - ((dp_wptr >= lnt)? STA_EOR: 0)); - if (dp_sta & STA_RDY) /* data buf full? */ - return dp_done (1, STA_DTRER); /* no, underrun */ - dp_wptr++; } /* next word */ - break; + case FNC_RW | FNC_2ND: /* read/write, word */ + if (dp_cw1 & CW1_RW) { /* write? */ + if (dp_sta & STA_RDY) /* timing failure? */ + return dp_wrdone (uptr, STA_DTRER); /* yes, error */ + if (r = dp_wrwd (uptr, dp_buf)) return r; /* wr word, error? */ + if (dp_eor) { /* transfer done? */ + dpxb[dp_rptr + REC_DATA + dp_wptr] = dp_csum; + return dp_wrdone (uptr, 0); /* clear busy, intr req */ + } + } + else { /* read? */ + lnt = dpxb[dp_rptr + REC_LNT] + dpxb[dp_rptr + REC_EXT]; + dp_buf = dpxb[dp_rptr + REC_DATA + dp_wptr];/* current word */ + dp_csum = dp_csum ^ dp_buf; /* xor to csum */ + if ((dp_wptr > lnt) || dp_eor) /* transfer done? */ + return dp_done (1, + (dp_csum? STA_CSMER: 0) | + ((dp_wptr >= lnt)? STA_EOR: 0)); + if (dp_sta & STA_RDY) /* data buf full? */ + return dp_done (1, STA_DTRER); /* no, underrun */ + dp_wptr++; /* next word */ + } + break; -default: - return SCPE_IERR; } /* end case */ + default: + return SCPE_IERR; + } /* end case */ -dp_sta = dp_sta | STA_RDY; /* set ready */ -if (dp_dma) SET_CH_REQ (ch); /* if DMA/DMC, req chan */ -sim_activate (uptr, dp_xtime); /* schedule word */ +dp_sta = dp_sta | STA_RDY; /* set ready */ +if (dp_dma) SET_CH_REQ (ch); /* if DMA/DMC, req chan */ +sim_activate (uptr, dp_xtime); /* schedule word */ return SCPE_OK; } - + /* Read track */ t_stat dp_rdtrk (UNIT *uptr, uint16 *buf, uint32 c, uint32 h) @@ -718,10 +768,11 @@ fseek (uptr->fileref, da * sizeof (uint16), SEEK_SET); l = fxread (buf, sizeof (uint16), DP_TRKLEN, uptr->fileref); for ( ; l < DP_TRKLEN; l++) buf[l] = 0; if (ferror (uptr->fileref)) { - perror ("DP I/O error"); - clearerr (uptr->fileref); - dp_done (1, STA_UNSER); - return SCPE_IOERR; } + perror ("DP I/O error"); + clearerr (uptr->fileref); + dp_done (1, STA_UNSER); + return SCPE_IOERR; + } return SCPE_OK; } @@ -734,10 +785,11 @@ uint32 da = ((c * dp_tab[dp_ctype].surf) + h) * DP_TRKLEN; fseek (uptr->fileref, da * sizeof (uint16), SEEK_SET); fxwrite (buf, sizeof (uint16), DP_TRKLEN, uptr->fileref); if (ferror (uptr->fileref)) { - perror ("DP I/O error"); - clearerr (uptr->fileref); - dp_done (1, STA_UNSER); - return SCPE_IOERR; } + perror ("DP I/O error"); + clearerr (uptr->fileref); + dp_done (1, STA_UNSER); + return SCPE_IOERR; + } return SCPE_OK; } @@ -747,11 +799,12 @@ t_bool dp_findrec (uint32 addr) { dp_rptr = 0; -do { if (dpxb[dp_rptr + REC_LNT] == 0) return FALSE; - if (dpxb[dp_rptr + REC_LNT] >= DP_TRKLEN) return TRUE; - if (dpxb[dp_rptr + REC_ADDR] == addr) return TRUE; - dp_rptr = dp_rptr + dpxb[dp_rptr + REC_LNT] + REC_OVHD; } -while (dp_rptr < DP_TRKLEN); +do { + if (dpxb[dp_rptr + REC_LNT] == 0) return FALSE; + if (dpxb[dp_rptr + REC_LNT] >= DP_TRKLEN) return TRUE; + if (dpxb[dp_rptr + REC_ADDR] == addr) return TRUE; + dp_rptr = dp_rptr + dpxb[dp_rptr + REC_LNT] + REC_OVHD; + } while (dp_rptr < DP_TRKLEN); return FALSE; } @@ -764,17 +817,19 @@ t_stat r; dp_csum = dp_csum ^ dat; if (dp_wptr < lnt) { - dpxb[dp_rptr + REC_DATA + dp_wptr++] = dat; - return SCPE_OK; } + dpxb[dp_rptr + REC_DATA + dp_wptr++] = dat; + return SCPE_OK; + } if (dp_wptr < (lnt + REC_MAXEXT)) { - dpxb[dp_rptr + REC_EXT]++; - dpxb[dp_rptr + REC_DATA + dp_wptr++] = dat; - return SCPE_OK; } -dpxb[dp_rptr + REC_DATA + dp_wptr] = dp_csum; /* write csum */ -dpxb[dp_rptr + lnt + REC_OVHD] = 0; /* zap rest of track */ -if (r = dp_wrdone (uptr, STA_UNSER)) return r; /* dump track */ + dpxb[dp_rptr + REC_EXT]++; + dpxb[dp_rptr + REC_DATA + dp_wptr++] = dat; + return SCPE_OK; + } +dpxb[dp_rptr + REC_DATA + dp_wptr] = dp_csum; /* write csum */ +dpxb[dp_rptr + lnt + REC_OVHD] = 0; /* zap rest of track */ +if (r = dp_wrdone (uptr, STA_UNSER)) return r; /* dump track */ return STOP_DPOVR; -} +} /* Write done, dump track, clear busy */ @@ -788,13 +843,13 @@ return dp_wrtrk (uptr, dpxb, uptr->CYL, CW1_GETHEAD (dp_cw1)); t_stat dp_done (uint32 req, uint32 flg) { -dp_xip = 0; /* clear xfr in prog */ -dp_sta = (dp_sta | flg) & ~(STA_BUSY | STA_MBZ); /* clear busy */ -if (req || dp_defint) SET_INT (INT_DP); /* if req, set intr */ -dp_defint = 0; /* clr def intr */ +dp_xip = 0; /* clear xfr in prog */ +dp_sta = (dp_sta | flg) & ~(STA_BUSY | STA_MBZ); /* clear busy */ +if (req || dp_defint) SET_INT (INT_DP); /* if req, set intr */ +dp_defint = 0; /* clr def intr */ return SCPE_OK; } - + /* Reset routine */ t_stat dp_reset (DEVICE *dptr) @@ -815,11 +870,12 @@ dp_wptr = 0; dp_bctr = 0; dp_gap = 0; dp_defint = 0; -for (i = 0; i < DP_NUMDRV; i++) { /* loop thru drives */ - sim_cancel (&dp_unit[i]); /* cancel activity */ - dp_unit[i].FNC = 0; /* clear function */ - dp_unit[i].CYL = 0; } -CLR_INT (INT_DP); /* clear int, enb */ +for (i = 0; i < DP_NUMDRV; i++) { /* loop thru drives */ + sim_cancel (&dp_unit[i]); /* cancel activity */ + dp_unit[i].FNC = 0; /* clear function */ + dp_unit[i].CYL = 0; + } +CLR_INT (INT_DP); /* clear int, enb */ CLR_ENB (INT_DP); return SCPE_OK; } @@ -831,7 +887,7 @@ t_stat dp_attach (UNIT *uptr, char *cptr) t_stat r; r = attach_unit (uptr, cptr); if (r != SCPE_OK) return r; -return dp_showformat (stdin, uptr, 0, NULL); +return dp_showformat (stdout, uptr, 0, NULL); } /* Set controller type */ @@ -842,9 +898,10 @@ int32 i; if ((val < 0) || (val >= DP_NUMTYP) || (cptr != NULL)) return SCPE_ARG; for (i = 0; i < DP_NUMDRV; i++) { - if (dp_unit[i].flags & UNIT_ATT) return SCPE_ALATT; } + if (dp_unit[i].flags & UNIT_ATT) return SCPE_ALATT; + } for (i = 0; i < DP_NUMDRV; i++) - dp_unit[i].capac = dp_tab[val].cap; + dp_unit[i].capac = dp_tab[val].cap; dp_ctype = val; return SCPE_OK; } @@ -863,13 +920,13 @@ return SCPE_OK; There is no standard format for record addresses. This routine provides two schemes: - -S sequential addressing (starting from 0) - default geometric addressing (8b: cylinder, 5b: head, 3b: sector) + -S sequential addressing (starting from 0) + default geometric addressing (8b: cylinder, 5b: head, 3b: sector) This routine also supports formatting by record count or word count: - -R argument is records per track - default argument is words per record + -R argument is records per track + default argument is words per record The relationship between words per record (W), bits per track (B), and records per track (R), is as follows: @@ -895,29 +952,33 @@ inp = (int32) get_uint (cptr, 10, 2048, &r); if (r != SCPE_OK) return r; if (inp == 0) return SCPE_ARG; finp = (float) inp; -if (sim_switches & SWMASK ('R')) { /* format records? */ - nr = inp; - nw = (int32) ((dp_tab[dp_ctype].wrds / (finp + ((finp - 1.0) / 20.0))) - REC_OVHD_WRDS); - if (nw <= 0) return SCPE_ARG; } -else { nw = inp; /* format words */ - nr = (int32) ((((20.0 * dp_tab[dp_ctype].wrds) / (finp + REC_OVHD_WRDS)) + 1.0) / 21.0); - if (nr <= 0) return SCPE_ARG; } +if (sim_switches & SWMASK ('R')) { /* format records? */ + nr = inp; + nw = (int32) ((dp_tab[dp_ctype].wrds / (finp + ((finp - 1.0) / 20.0))) - REC_OVHD_WRDS); + if (nw <= 0) return SCPE_ARG; + } +else { + nw = inp; /* format words */ + nr = (int32) ((((20.0 * dp_tab[dp_ctype].wrds) / (finp + REC_OVHD_WRDS)) + 1.0) / 21.0); + if (nr <= 0) return SCPE_ARG; + } printf ("Proposed format: records/track = %d, record size = %d\n", nr, nw); if (!get_yn ("Formatting will destroy all data on this disk; proceed? [N]", FALSE)) - return SCPE_OK; + return SCPE_OK; for (c = cntr = 0; c < dp_tab[dp_ctype].cyl; c++) { - for (h = 0; h < dp_tab[dp_ctype].surf; h++) { - for (i = 0; i < DP_TRKLEN; i++) tbuf[i] = 0; - rptr = 0; - for (i = 0; i < nr; i++) { - tbuf[rptr + REC_LNT] = nw & DMASK; - if (sim_switches & SWMASK ('S')) - tbuf[rptr + REC_ADDR] = cntr++; - else tbuf[rptr + REC_ADDR] = (c << 8) + (h << 3) + i; - rptr = rptr + nw + REC_OVHD; } - if (r = dp_wrtrk (uptr, tbuf, c, h)) return r; - } - } + for (h = 0; h < dp_tab[dp_ctype].surf; h++) { + for (i = 0; i < DP_TRKLEN; i++) tbuf[i] = 0; + rptr = 0; + for (i = 0; i < nr; i++) { + tbuf[rptr + REC_LNT] = nw & DMASK; + if (sim_switches & SWMASK ('S')) + tbuf[rptr + REC_ADDR] = cntr++; + else tbuf[rptr + REC_ADDR] = (c << 8) + (h << 3) + i; + rptr = rptr + nw + REC_OVHD; + } + if (r = dp_wrtrk (uptr, tbuf, c, h)) return r; + } + } printf ("Formatting complete\n"); return SCPE_OK; } @@ -937,44 +998,47 @@ t_stat r; if (uptr == NULL) return SCPE_IERR; if ((uptr->flags & UNIT_ATT) == 0) return SCPE_UNATT; for (c = 0; c < dp_tab[dp_ctype].cyl; c++) { - for (h = 0; h < dp_tab[dp_ctype].surf; h++) { - if (r = dp_rdtrk (uptr, tbuf, c, h)) return r; - rptr = 0; - rlnt = tbuf[rptr + REC_LNT]; - if (rlnt == 0) { - if (c || h) fprintf (st, - "Unformatted track, cyl = %d, head = %d\n", c, h); - else fprintf (st, "Disk is unformatted\n"); - return SCPE_OK; } - for (sec = 0; rlnt != 0; sec++) { - if ((rptr + rlnt + REC_OVHD) >= DP_TRKLEN) { - fprintf (st, "Invalid record length %d, cyl = %d, head = %d, sect = %d\n", - rlnt, c, h, sec); - return SCPE_OK; } - if (tbuf[rptr + REC_EXT] >= REC_MAXEXT) { - fprintf (st, "Invalid record extension %d, cyl = %d, head = %d, sect = %d\n", - tbuf[rptr + REC_EXT], c, h, sec); - return SCPE_OK; } - if (rlnt > maxrec) maxrec = rlnt; - if (rlnt < minrec) minrec = rlnt; - rptr = rptr + rlnt + REC_OVHD; - rlnt = tbuf[rptr + REC_LNT]; - } - if (sec > maxsec) maxsec = sec; - if (sec < minsec) minsec = sec; - } - } + for (h = 0; h < dp_tab[dp_ctype].surf; h++) { + if (r = dp_rdtrk (uptr, tbuf, c, h)) return r; + rptr = 0; + rlnt = tbuf[rptr + REC_LNT]; + if (rlnt == 0) { + if (c || h) fprintf (st, + "Unformatted track, cyl = %d, head = %d\n", c, h); + else fprintf (st, "Disk is unformatted\n"); + return SCPE_OK; + } + for (sec = 0; rlnt != 0; sec++) { + if ((rptr + rlnt + REC_OVHD) >= DP_TRKLEN) { + fprintf (st, "Invalid record length %d, cyl = %d, head = %d, sect = %d\n", + rlnt, c, h, sec); + return SCPE_OK; + } + if (tbuf[rptr + REC_EXT] >= REC_MAXEXT) { + fprintf (st, "Invalid record extension %d, cyl = %d, head = %d, sect = %d\n", + tbuf[rptr + REC_EXT], c, h, sec); + return SCPE_OK; + } + if (rlnt > maxrec) maxrec = rlnt; + if (rlnt < minrec) minrec = rlnt; + rptr = rptr + rlnt + REC_OVHD; + rlnt = tbuf[rptr + REC_LNT]; + } + if (sec > maxsec) maxsec = sec; + if (sec < minsec) minsec = sec; + } + } if ((minrec == maxrec) && (minsec == maxsec)) fprintf (st, - "Valid fixed format, records/track = %d, record size = %d\n", - minsec, minrec); + "Valid fixed format, records/track = %d, record size = %d\n", + minsec, minrec); else if (minrec == maxrec) fprintf (st, - "Valid variable format, records/track = %d-%d, record size = %d\n", - minsec, maxsec, minrec); + "Valid variable format, records/track = %d-%d, record size = %d\n", + minsec, maxsec, minrec); else if (minsec == maxsec) fprintf (st, - "Valid variable format, records/track = %d, record sizes = %d-%d\n", - minsec, minrec, maxrec); + "Valid variable format, records/track = %d, record sizes = %d-%d\n", + minsec, minrec, maxrec); else fprintf (st, - "Valid variable format, records/track = %d-%d, record sizes = %d-%d\n", - minsec, maxsec, minrec, maxrec); + "Valid variable format, records/track = %d-%d, record sizes = %d-%d\n", + minsec, maxsec, minrec, maxrec); return SCPE_OK; } diff --git a/H316/h316_fhd.c b/H316/h316_fhd.c index 921a295f..c4d36c80 100644 --- a/H316/h316_fhd.c +++ b/H316/h316_fhd.c @@ -1,6 +1,6 @@ /* h316_fhd.c: H316/516 fixed head simulator - Copyright (c) 2003-2004, Robert M. Supnik + Copyright (c) 2003-2005, 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"), @@ -19,13 +19,13 @@ 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 + 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 516-4400 fixed head disk + fhd 516-4400 fixed head disk - 04-Jan-04 RMS Changed sim_fsize calling sequence + 04-Jan-04 RMS Changed sim_fsize calling sequence These head-per-track devices are buffered in memory, to minimize overhead. */ @@ -35,59 +35,59 @@ /* Constants */ -#define FH_NUMWD 1536 /* words/track */ -#define FH_NUMTK 64 /* tracks/surface */ -#define FH_WDPSF (FH_NUMWD * FH_NUMTK) /* words/surface */ -#define FH_NUMSF 16 /* surfaces/ctlr */ -#define UNIT_V_AUTO (UNIT_V_UF + 0) /* autosize */ -#define UNIT_V_SF (UNIT_V_UF + 1) /* #surfaces - 1 */ -#define UNIT_M_SF 017 -#define UNIT_AUTO (1 << UNIT_V_AUTO) -#define UNIT_SF (UNIT_M_SF << UNIT_V_SF) -#define UNIT_GETSF(x) ((((x) >> UNIT_V_SF) & UNIT_M_SF) + 1) +#define FH_NUMWD 1536 /* words/track */ +#define FH_NUMTK 64 /* tracks/surface */ +#define FH_WDPSF (FH_NUMWD * FH_NUMTK) /* words/surface */ +#define FH_NUMSF 16 /* surfaces/ctlr */ +#define UNIT_V_AUTO (UNIT_V_UF + 0) /* autosize */ +#define UNIT_V_SF (UNIT_V_UF + 1) /* #surfaces - 1 */ +#define UNIT_M_SF 017 +#define UNIT_AUTO (1 << UNIT_V_AUTO) +#define UNIT_SF (UNIT_M_SF << UNIT_V_SF) +#define UNIT_GETSF(x) ((((x) >> UNIT_V_SF) & UNIT_M_SF) + 1) /* Command word 1 */ -#define CW1_RW 0100000 /* read vs write */ -#define CW1_V_SF 10 /* surface */ -#define CW1_M_SF 017 -#define CW1_GETSF(x) (((x) >> CW1_V_SF) & CW1_M_SF) -#define CW1_V_TK 4 /* track */ -#define CW1_M_TK 077 -#define CW1_GETTK(x) (((x) >> CW1_V_TK) & CW1_M_TK) +#define CW1_RW 0100000 /* read vs write */ +#define CW1_V_SF 10 /* surface */ +#define CW1_M_SF 017 +#define CW1_GETSF(x) (((x) >> CW1_V_SF) & CW1_M_SF) +#define CW1_V_TK 4 /* track */ +#define CW1_M_TK 077 +#define CW1_GETTK(x) (((x) >> CW1_V_TK) & CW1_M_TK) /* Command word 2 */ -#define CW2_V_CA 0 /* character addr */ -#define CW2_M_CA 07777 -#define CW2_GETCA(x) (((x) >> CW2_V_CA) & CW2_M_CA) +#define CW2_V_CA 0 /* character addr */ +#define CW2_M_CA 07777 +#define CW2_GETCA(x) (((x) >> CW2_V_CA) & CW2_M_CA) -#define GET_POS(x) ((int) fmod (sim_gtime() / ((double) (x)), \ - ((double) FH_NUMWD))) +#define GET_POS(x) ((int) fmod (sim_gtime() / ((double) (x)), \ + ((double) FH_NUMWD))) /* OTA states */ -#define OTA_NOP 0 /* normal */ -#define OTA_CW1 1 /* expecting CW1 */ -#define OTA_CW2 2 /* expecting CW2 */ - +#define OTA_NOP 0 /* normal */ +#define OTA_CW1 1 /* expecting CW1 */ +#define OTA_CW2 2 /* expecting CW2 */ + extern int32 dev_int, dev_enb, chan_req; extern int32 stop_inst; extern uint32 dma_ad[DMA_MAX]; -uint32 fhd_cw1 = 0; /* cmd word 1 */ -uint32 fhd_cw2 = 0; /* cmd word 2 */ -uint32 fhd_buf = 0; /* buffer */ -uint32 fhd_otas = 0; /* state */ -uint32 fhd_busy = 0; /* busy */ -uint32 fhd_rdy = 0; /* word ready */ -uint32 fhd_dte = 0; /* data err */ -uint32 fhd_ace = 0; /* access error */ -uint32 fhd_dma = 0; /* DMA/DMC */ -uint32 fhd_eor = 0; /* end of range */ -uint32 fhd_csum = 0; /* parity checksum */ -uint32 fhd_stopioe = 1; /* stop on error */ -int32 fhd_time = 10; /* time per word */ +uint32 fhd_cw1 = 0; /* cmd word 1 */ +uint32 fhd_cw2 = 0; /* cmd word 2 */ +uint32 fhd_buf = 0; /* buffer */ +uint32 fhd_otas = 0; /* state */ +uint32 fhd_busy = 0; /* busy */ +uint32 fhd_rdy = 0; /* word ready */ +uint32 fhd_dte = 0; /* data err */ +uint32 fhd_ace = 0; /* access error */ +uint32 fhd_dma = 0; /* DMA/DMC */ +uint32 fhd_eor = 0; /* end of range */ +uint32 fhd_csum = 0; /* parity checksum */ +uint32 fhd_stopioe = 1; /* stop on error */ +int32 fhd_time = 10; /* time per word */ int32 fhdio (int32 inst, int32 fnc, int32 dat, int32 dev); t_stat fhd_svc (UNIT *uptr); @@ -105,133 +105,148 @@ uint32 fhd_csword (uint32 cs, uint32 ch); /* FHD data structures - fhd_dev device descriptor - fhd_unit unit descriptor - fhd_mod unit modifiers - fhd_reg register list + fhd_dev device descriptor + fhd_unit unit descriptor + fhd_mod unit modifiers + fhd_reg register list */ DIB fhd_dib = { FHD, IOBUS, 1, &fhdio }; -UNIT fhd_unit = - { UDATA (&fhd_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_BUFABLE+ - UNIT_MUSTBUF, FH_WDPSF) }; +UNIT fhd_unit = { + UDATA (&fhd_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_BUFABLE+UNIT_MUSTBUF, + FH_WDPSF) + }; REG fhd_reg[] = { - { ORDATA (CW1, fhd_cw1, 16) }, - { ORDATA (CW2, fhd_cw2, 16) }, - { ORDATA (BUF, fhd_buf, 16) }, - { FLDATA (BUSY, fhd_busy, 0) }, - { FLDATA (RDY, fhd_rdy, 0) }, - { FLDATA (DTE, fhd_dte, 0) }, - { FLDATA (ACE, fhd_ace, 0) }, - { FLDATA (EOR, fhd_eor, 0) }, - { FLDATA (DMA, fhd_dma, 0) }, - { FLDATA (CSUM, fhd_csum, 7) }, - { FLDATA (INTREQ, dev_int, INT_V_MT) }, - { FLDATA (ENABLE, dev_enb, INT_V_MT) }, - { DRDATA (TIME, fhd_time, 31), REG_NZ + PV_LEFT }, - { ORDATA (OTAS, fhd_otas, 2), REG_HRO }, - { ORDATA (CHAN, fhd_dib.chan, 5), REG_HRO }, - { FLDATA (STOP_IOE, fhd_stopioe, 0) }, - { NULL } }; + { ORDATA (CW1, fhd_cw1, 16) }, + { ORDATA (CW2, fhd_cw2, 16) }, + { ORDATA (BUF, fhd_buf, 16) }, + { FLDATA (BUSY, fhd_busy, 0) }, + { FLDATA (RDY, fhd_rdy, 0) }, + { FLDATA (DTE, fhd_dte, 0) }, + { FLDATA (ACE, fhd_ace, 0) }, + { FLDATA (EOR, fhd_eor, 0) }, + { FLDATA (DMA, fhd_dma, 0) }, + { FLDATA (CSUM, fhd_csum, 7) }, + { FLDATA (INTREQ, dev_int, INT_V_MT) }, + { FLDATA (ENABLE, dev_enb, INT_V_MT) }, + { DRDATA (TIME, fhd_time, 31), REG_NZ + PV_LEFT }, + { ORDATA (OTAS, fhd_otas, 2), REG_HRO }, + { ORDATA (CHAN, fhd_dib.chan, 5), REG_HRO }, + { FLDATA (STOP_IOE, fhd_stopioe, 0) }, + { NULL } + }; MTAB fhd_mod[] = { - { UNIT_SF, (0 << UNIT_V_SF), NULL, "1S", &fhd_set_size }, - { UNIT_SF, (1 << UNIT_V_SF), NULL, "2S", &fhd_set_size }, - { UNIT_SF, (2 << UNIT_V_SF), NULL, "3S", &fhd_set_size }, - { UNIT_SF, (3 << UNIT_V_SF), NULL, "4S", &fhd_set_size }, - { UNIT_SF, (4 << UNIT_V_SF), NULL, "5S", &fhd_set_size }, - { UNIT_SF, (5 << UNIT_V_SF), NULL, "6S", &fhd_set_size }, - { UNIT_SF, (6 << UNIT_V_SF), NULL, "7S", &fhd_set_size }, - { UNIT_SF, (7 << UNIT_V_SF), NULL, "8S", &fhd_set_size }, - { UNIT_SF, (8 << UNIT_V_SF), NULL, "9S", &fhd_set_size }, - { UNIT_SF, (9 << UNIT_V_SF), NULL, "10S", &fhd_set_size }, - { UNIT_SF, (10 << UNIT_V_SF), NULL, "11S", &fhd_set_size }, - { UNIT_SF, (11 << UNIT_V_SF), NULL, "12S", &fhd_set_size }, - { UNIT_SF, (12 << UNIT_V_SF), NULL, "13S", &fhd_set_size }, - { UNIT_SF, (13 << UNIT_V_SF), NULL, "14S", &fhd_set_size }, - { UNIT_SF, (14 << UNIT_V_SF), NULL, "15S", &fhd_set_size }, - { UNIT_SF, (15 << UNIT_V_SF), NULL, "16S", &fhd_set_size }, - { UNIT_AUTO, UNIT_AUTO, "autosize", "AUTOSIZE", NULL }, - { MTAB_XTD|MTAB_VDV, 0, NULL, "IOBUS", - &io_set_iobus, NULL, NULL }, - { MTAB_XTD|MTAB_VDV, 0, NULL, "DMC", - &io_set_dmc, NULL, NULL }, - { MTAB_XTD|MTAB_VDV, 0, NULL, "DMA", - &io_set_dma, NULL, NULL }, - { MTAB_XTD|MTAB_VDV, 0, "CHANNEL", NULL, - NULL, &io_show_chan, NULL }, - { 0 } }; + { UNIT_SF, (0 << UNIT_V_SF), NULL, "1S", &fhd_set_size }, + { UNIT_SF, (1 << UNIT_V_SF), NULL, "2S", &fhd_set_size }, + { UNIT_SF, (2 << UNIT_V_SF), NULL, "3S", &fhd_set_size }, + { UNIT_SF, (3 << UNIT_V_SF), NULL, "4S", &fhd_set_size }, + { UNIT_SF, (4 << UNIT_V_SF), NULL, "5S", &fhd_set_size }, + { UNIT_SF, (5 << UNIT_V_SF), NULL, "6S", &fhd_set_size }, + { UNIT_SF, (6 << UNIT_V_SF), NULL, "7S", &fhd_set_size }, + { UNIT_SF, (7 << UNIT_V_SF), NULL, "8S", &fhd_set_size }, + { UNIT_SF, (8 << UNIT_V_SF), NULL, "9S", &fhd_set_size }, + { UNIT_SF, (9 << UNIT_V_SF), NULL, "10S", &fhd_set_size }, + { UNIT_SF, (10 << UNIT_V_SF), NULL, "11S", &fhd_set_size }, + { UNIT_SF, (11 << UNIT_V_SF), NULL, "12S", &fhd_set_size }, + { UNIT_SF, (12 << UNIT_V_SF), NULL, "13S", &fhd_set_size }, + { UNIT_SF, (13 << UNIT_V_SF), NULL, "14S", &fhd_set_size }, + { UNIT_SF, (14 << UNIT_V_SF), NULL, "15S", &fhd_set_size }, + { UNIT_SF, (15 << UNIT_V_SF), NULL, "16S", &fhd_set_size }, + { UNIT_AUTO, UNIT_AUTO, "autosize", "AUTOSIZE", NULL }, + { MTAB_XTD|MTAB_VDV, 0, NULL, "IOBUS", + &io_set_iobus, NULL, NULL }, + { MTAB_XTD|MTAB_VDV, 0, NULL, "DMC", + &io_set_dmc, NULL, NULL }, + { MTAB_XTD|MTAB_VDV, 0, NULL, "DMA", + &io_set_dma, NULL, NULL }, + { MTAB_XTD|MTAB_VDV, 0, "CHANNEL", NULL, + NULL, &io_show_chan, NULL }, + { 0 } + }; DEVICE fhd_dev = { - "FHD", &fhd_unit, fhd_reg, fhd_mod, - 1, 8, 22, 1, 8, 16, - NULL, NULL, &fhd_reset, - NULL, &fhd_attach, NULL, - &fhd_dib, DEV_DISABLE }; - + "FHD", &fhd_unit, fhd_reg, fhd_mod, + 1, 8, 22, 1, 8, 16, + NULL, NULL, &fhd_reset, + NULL, &fhd_attach, NULL, + &fhd_dib, DEV_DISABLE + }; + /* IO routines */ int32 fhdio (int32 inst, int32 fnc, int32 dat, int32 dev) { -switch (inst) { /* case on opcode */ -case ioOCP: /* control */ - if (fnc == 04) { /* terminate output? */ - fhd_eor = 1; /* stop */ - CLR_INT (INT_FHD); } /* clear int req */ - else if (fnc == 003) fhd_go (1); /* start, DMA */ - else if (fnc == 007) fhd_go (0); /* start, IO bus */ - else return IOBADFNC (dat); - break; -case ioOTA: /* output */ - if (fnc) return IOBADFNC (dat); /* only fnc 0 */ - if (fhd_rdy) { /* ready? */ - fhd_buf = dat; /* store data */ - if (fhd_otas == OTA_CW1) fhd_go1 (dat); /* expecting CW1? */ - else if (fhd_otas == OTA_CW2) fhd_go2 (dat);/* expecting CW2? */ - else fhd_rdy = 0; /* normal, clr ready */ - return IOSKIP (dat); } - break; -case ioINA: /* input */ - if (fnc) return IOBADFNC (dat); /* only fnc 0 */ - if (fhd_rdy) { /* ready? */ - fhd_rdy = 0; /* clear ready */ - return IOSKIP (dat | fhd_buf); } /* return data */ - break; -case ioSKS: /* sense */ - if (((fnc == 000) && fhd_rdy) || /* 0 = skip if ready */ - ((fnc == 001) && !fhd_busy) || /* 1 = skip if !busy */ - ((fnc == 002) && !fhd_dte) || /* 2 = skip if !data err */ - ((fnc == 003) && !fhd_ace) || /* 3 = skip if !access err */ - ((fnc == 004) && !TST_INTREQ (INT_FHD))) /* 4 = skip if !interrupt */ - return IOSKIP (dat); - break; -case ioEND: - fhd_eor = 1; - break; } +switch (inst) { /* case on opcode */ + + case ioOCP: /* control */ + if (fnc == 04) { /* terminate output? */ + fhd_eor = 1; /* stop */ + CLR_INT (INT_FHD); /* clear int req */ + } + else if (fnc == 003) fhd_go (1); /* start, DMA */ + else if (fnc == 007) fhd_go (0); /* start, IO bus */ + else return IOBADFNC (dat); + break; + + case ioOTA: /* output */ + if (fnc) return IOBADFNC (dat); /* only fnc 0 */ + if (fhd_rdy) { /* ready? */ + fhd_buf = dat; /* store data */ + if (fhd_otas == OTA_CW1) fhd_go1 (dat); /* expecting CW1? */ + else if (fhd_otas == OTA_CW2) fhd_go2 (dat);/* expecting CW2? */ + else fhd_rdy = 0; /* normal, clr ready */ + return IOSKIP (dat); + } + break; + + case ioINA: /* input */ + if (fnc) return IOBADFNC (dat); /* only fnc 0 */ + if (fhd_rdy) { /* ready? */ + fhd_rdy = 0; /* clear ready */ + return IOSKIP (dat | fhd_buf); /* return data */ + } + break; + + case ioSKS: /* sense */ + if (((fnc == 000) && fhd_rdy) || /* 0 = skip if ready */ + ((fnc == 001) && !fhd_busy) || /* 1 = skip if !busy */ + ((fnc == 002) && !fhd_dte) || /* 2 = skip if !data err */ + ((fnc == 003) && !fhd_ace) || /* 3 = skip if !access err */ + ((fnc == 004) && !TST_INTREQ (INT_FHD))) /* 4 = skip if !interrupt */ + return IOSKIP (dat); + break; + + case ioEND: + fhd_eor = 1; + break; + } + return dat; } - + /* Start new operation */ void fhd_go (uint32 dma) { -int32 ch = fhd_dib.chan - 1; /* DMA/DMC chan */ +int32 ch = fhd_dib.chan - 1; /* DMA/DMC chan */ -if (fhd_busy) return; /* ignore if busy */ -fhd_busy = 1; /* ctlr is busy */ -fhd_eor = 0; /* transfer not done */ -fhd_csum = 0; /* init checksum */ -fhd_dte = 0; /* clear errors */ +if (fhd_busy) return; /* ignore if busy */ +fhd_busy = 1; /* ctlr is busy */ +fhd_eor = 0; /* transfer not done */ +fhd_csum = 0; /* init checksum */ +fhd_dte = 0; /* clear errors */ fhd_ace = 0; -if (ch >= 0) fhd_dma = dma; /* DMA allowed? */ -else fhd_dma = 0; /* no, force IO bus */ -fhd_otas = OTA_CW1; /* expect CW1 */ -fhd_rdy = 1; /* set ready */ -if (fhd_dma && Q_DMA (ch)) { /* DMA and DMA channel? */ - SET_CH_REQ (ch); /* set channel request */ - dma_ad[ch] = dma_ad[ch] & ~DMA_IN; } /* force output */ +if (ch >= 0) fhd_dma = dma; /* DMA allowed? */ +else fhd_dma = 0; /* no, force IO bus */ +fhd_otas = OTA_CW1; /* expect CW1 */ +fhd_rdy = 1; /* set ready */ +if (fhd_dma && Q_DMA (ch)) { /* DMA and DMA channel? */ + SET_CH_REQ (ch); /* set channel request */ + dma_ad[ch] = dma_ad[ch] & ~DMA_IN; /* force output */ + } return; } @@ -239,12 +254,12 @@ return; void fhd_go1 (uint32 dat) { -int32 ch = fhd_dib.chan - 1; /* DMA/DMC chan */ +int32 ch = fhd_dib.chan - 1; /* DMA/DMC chan */ -fhd_cw1 = dat; /* store CW1 */ -fhd_otas = OTA_CW2; /* expect CW2 */ -fhd_rdy = 1; /* set ready */ -if (fhd_dma && Q_DMA (ch)) SET_CH_REQ (ch); /* DMA? set chan request */ +fhd_cw1 = dat; /* store CW1 */ +fhd_otas = OTA_CW2; /* expect CW2 */ +fhd_rdy = 1; /* set ready */ +if (fhd_dma && Q_DMA (ch)) SET_CH_REQ (ch); /* DMA? set chan request */ return; } @@ -252,89 +267,101 @@ return; void fhd_go2 (uint32 dat) { -int32 ch = fhd_dib.chan - 1; /* DMA/DMC chan */ -uint32 sf = CW1_GETSF (fhd_cw1); /* surface */ +int32 ch = fhd_dib.chan - 1; /* DMA/DMC chan */ +uint32 sf = CW1_GETSF (fhd_cw1); /* surface */ int32 t, wa; -fhd_cw2 = dat; /* store CW2 */ -fhd_otas = OTA_NOP; /* next state */ -wa = CW2_GETCA (fhd_cw2) >> 1; /* word addr */ -if ((wa >= FH_NUMWD) || /* if bad char addr */ - ((fhd_unit.flags & UNIT_ATT) == 0) || /* or unattached */ - (sf >= UNIT_GETSF (fhd_unit.flags))) { /* or bad surface */ - fhd_ace = 1; /* access error */ - fhd_busy = 0; /* abort operation */ - SET_INT (INT_FHD); - return; } -if (fhd_cw1 & CW1_RW) { /* write? */ - fhd_rdy = 1; /* set ready */ - if (fhd_dma) SET_CH_REQ (ch); } /* if DMA/DMC, req chan */ -else { fhd_rdy = 0; /* read, clear ready */ - if (fhd_dma && (ch < DMC_V_DMC1)) /* read and DMA chan? */ - dma_ad[ch] = dma_ad[ch] | DMA_IN; } /* force input */ -t = wa - GET_POS (fhd_time); /* delta to new loc */ -if (t < 0) t = t + FH_NUMWD; /* wrap around? */ -sim_activate (&fhd_unit, t * fhd_time); /* schedule op */ +fhd_cw2 = dat; /* store CW2 */ +fhd_otas = OTA_NOP; /* next state */ +wa = CW2_GETCA (fhd_cw2) >> 1; /* word addr */ +if ((wa >= FH_NUMWD) || /* if bad char addr */ + ((fhd_unit.flags & UNIT_ATT) == 0) || /* or unattached */ + (sf >= UNIT_GETSF (fhd_unit.flags))) { /* or bad surface */ + fhd_ace = 1; /* access error */ + fhd_busy = 0; /* abort operation */ + SET_INT (INT_FHD); + return; + } +if (fhd_cw1 & CW1_RW) { /* write? */ + fhd_rdy = 1; /* set ready */ + if (fhd_dma) SET_CH_REQ (ch); /* if DMA/DMC, req chan */ + } +else { + fhd_rdy = 0; /* read, clear ready */ + if (fhd_dma && (ch < DMC_V_DMC1)) /* read and DMA chan? */ + dma_ad[ch] = dma_ad[ch] | DMA_IN; /* force input */ + } +t = wa - GET_POS (fhd_time); /* delta to new loc */ +if (t < 0) t = t + FH_NUMWD; /* wrap around? */ +sim_activate (&fhd_unit, t * fhd_time); /* schedule op */ return; } - + /* Unit service */ t_stat fhd_svc (UNIT *uptr) { -int32 ch = fhd_dib.chan - 1; /* DMA/DMC chan (-1 if IO bus) */ +int32 ch = fhd_dib.chan - 1; /* DMA/DMC chan (-1 if IO bus) */ uint32 c1, c2; -if ((uptr->flags & UNIT_ATT) == 0) { /* unattached? */ - fhd_ace = 1; /* access error */ - fhd_busy = 0; /* abort operation */ - SET_INT (INT_FHD); - return IORETURN (fhd_stopioe, SCPE_UNATT); } +if ((uptr->flags & UNIT_ATT) == 0) { /* unattached? */ + fhd_ace = 1; /* access error */ + fhd_busy = 0; /* abort operation */ + SET_INT (INT_FHD); + return IORETURN (fhd_stopioe, SCPE_UNATT); + } -if (fhd_eor || fhd_rdy) { /* done or ready set? */ - if (fhd_rdy) fhd_dte = 1; /* if ready set, data err */ - if (fhd_cw1 & CW1_RW) { /* write? */ - if (!fhd_rdy) { /* buffer full? */ - fhd_putc (uptr, fhd_buf >> 8); /* store last word */ - fhd_putc (uptr, fhd_buf); } - fhd_putc (uptr, fhd_csum); } /* store csum */ - else { /* read */ - fhd_getc (uptr, &c1); /* get csum */ - if (fhd_csum) fhd_dte = 1; } /* if csum != 0, err */ - fhd_busy = 0; /* operation complete */ - SET_INT (INT_FHD); - return SCPE_OK; } +if (fhd_eor || fhd_rdy) { /* done or ready set? */ + if (fhd_rdy) fhd_dte = 1; /* if ready set, data err */ + if (fhd_cw1 & CW1_RW) { /* write? */ + if (!fhd_rdy) { /* buffer full? */ + fhd_putc (uptr, fhd_buf >> 8); /* store last word */ + fhd_putc (uptr, fhd_buf); + } + fhd_putc (uptr, fhd_csum); /* store csum */ + } + else { /* read */ + fhd_getc (uptr, &c1); /* get csum */ + if (fhd_csum) fhd_dte = 1; /* if csum != 0, err */ + } + fhd_busy = 0; /* operation complete */ + SET_INT (INT_FHD); + return SCPE_OK; + } -if (fhd_cw1 & CW1_RW) { /* write? */ - if (fhd_putc (uptr, fhd_buf >> 8)) return SCPE_OK; - if (fhd_putc (uptr, fhd_buf)) return SCPE_OK; } -else { if (fhd_getc (uptr, &c1)) return SCPE_OK; /* read */ - if (fhd_getc (uptr, &c2)) return SCPE_OK; - fhd_buf = (c1 << 8) | c2; } -sim_activate (uptr, fhd_time); /* next word */ -fhd_rdy = 1; /* set ready */ -if (fhd_dma) SET_CH_REQ (ch); /* if DMA/DMC, req chan */ +if (fhd_cw1 & CW1_RW) { /* write? */ + if (fhd_putc (uptr, fhd_buf >> 8)) return SCPE_OK; + if (fhd_putc (uptr, fhd_buf)) return SCPE_OK; + } +else { + if (fhd_getc (uptr, &c1)) return SCPE_OK; /* read */ + if (fhd_getc (uptr, &c2)) return SCPE_OK; + fhd_buf = (c1 << 8) | c2; + } +sim_activate (uptr, fhd_time); /* next word */ +fhd_rdy = 1; /* set ready */ +if (fhd_dma) SET_CH_REQ (ch); /* if DMA/DMC, req chan */ return SCPE_OK; } - + /* Read character from disk */ t_bool fhd_getc (UNIT *uptr, uint32 *ch) { -uint32 sf = CW1_GETSF (fhd_cw1); /* surface */ -uint32 tk = CW1_GETTK (fhd_cw1); /* track */ -uint32 ca = CW2_GETCA (fhd_cw2); /* char addr */ -uint32 wa = ca >> 1; /* word addr */ -uint32 ba = (((sf * FH_NUMTK) + tk) * FH_NUMWD) + wa; /* buffer offset */ -uint16 *fbuf = uptr->filebuf; /* buffer base */ +uint32 sf = CW1_GETSF (fhd_cw1); /* surface */ +uint32 tk = CW1_GETTK (fhd_cw1); /* track */ +uint32 ca = CW2_GETCA (fhd_cw2); /* char addr */ +uint32 wa = ca >> 1; /* word addr */ +uint32 ba = (((sf * FH_NUMTK) + tk) * FH_NUMWD) + wa; /* buffer offset */ +uint16 *fbuf = uptr->filebuf; /* buffer base */ uint32 wd; -if (fhd_bad_wa (wa)) return TRUE; /* addr bad? */ -fhd_cw2 = fhd_cw2 + 1; /* incr char addr */ -if (ca & 1) wd = fbuf[ba] & 0377; /* select char */ +if (fhd_bad_wa (wa)) return TRUE; /* addr bad? */ +fhd_cw2 = fhd_cw2 + 1; /* incr char addr */ +if (ca & 1) wd = fbuf[ba] & 0377; /* select char */ else wd = (fbuf[ba] >> 8) & 0377; -fhd_csum = fhd_csword (fhd_csum, wd); /* put in csum */ -*ch = wd; /* return */ +fhd_csum = fhd_csword (fhd_csum, wd); /* put in csum */ +*ch = wd; /* return */ return FALSE; } @@ -342,20 +369,20 @@ return FALSE; t_bool fhd_putc (UNIT *uptr, uint32 ch) { -uint32 sf = CW1_GETSF (fhd_cw1); /* surface */ -uint32 tk = CW1_GETTK (fhd_cw1); /* track */ -uint32 ca = CW2_GETCA (fhd_cw2); /* char addr */ -uint32 wa = ca >> 1; /* word addr */ -uint32 ba = (((sf * FH_NUMTK) + tk) * FH_NUMWD) + wa; /* buffer offset */ -uint16 *fbuf = uptr->filebuf; /* buffer base */ +uint32 sf = CW1_GETSF (fhd_cw1); /* surface */ +uint32 tk = CW1_GETTK (fhd_cw1); /* track */ +uint32 ca = CW2_GETCA (fhd_cw2); /* char addr */ +uint32 wa = ca >> 1; /* word addr */ +uint32 ba = (((sf * FH_NUMTK) + tk) * FH_NUMWD) + wa; /* buffer offset */ +uint16 *fbuf = uptr->filebuf; /* buffer base */ -ch = ch & 0377; /* mask char */ -if (fhd_bad_wa (wa)) return TRUE; /* addr bad? */ -fhd_cw2 = fhd_cw2 + 1; /* incr char addr */ -if (ca & 1) fbuf[ba] = (fbuf[ba] & ~0377) | ch; /* odd? low char */ -else fbuf[ba] = (fbuf[ba] & 0377) | (ch << 8); /* even, hi char */ -fhd_csum = fhd_csword (fhd_csum, ch); /* put in csum */ -if (ba >= uptr->hwmark) uptr->hwmark = ba + 1; /* update hwmark */ +ch = ch & 0377; /* mask char */ +if (fhd_bad_wa (wa)) return TRUE; /* addr bad? */ +fhd_cw2 = fhd_cw2 + 1; /* incr char addr */ +if (ca & 1) fbuf[ba] = (fbuf[ba] & ~0377) | ch; /* odd? low char */ +else fbuf[ba] = (fbuf[ba] & 0377) | (ch << 8); /* even, hi char */ +fhd_csum = fhd_csword (fhd_csum, ch); /* put in csum */ +if (ba >= uptr->hwmark) uptr->hwmark = ba + 1; /* update hwmark */ return FALSE; } @@ -363,11 +390,12 @@ return FALSE; t_bool fhd_bad_wa (uint32 wa) { -if (wa >= FH_NUMWD) { /* bad address? */ - fhd_ace = 1; /* access error */ - fhd_busy = 0; /* abort operation */ - SET_INT (INT_FHD); - return TRUE; } +if (wa >= FH_NUMWD) { /* bad address? */ + fhd_ace = 1; /* access error */ + fhd_busy = 0; /* abort operation */ + SET_INT (INT_FHD); + return TRUE; + } return FALSE; } @@ -375,26 +403,27 @@ return FALSE; uint32 fhd_csword (uint32 cs, uint32 ch) { -while (ch) { /* count bits */ - ch = ch & ~(ch & (-(int32) ch)); - cs = cs ^ 0200; } /* invert cs for each 1 */ +while (ch) { /* count bits */ + ch = ch & ~(ch & (-(int32) ch)); + cs = cs ^ 0200; /* invert cs for each 1 */ + } return cs; } - + /* Reset routine */ t_stat fhd_reset (DEVICE *dptr) { -fhd_busy = 0; /* reset state */ +fhd_busy = 0; /* reset state */ fhd_rdy = 0; fhd_ace = 0; fhd_dte = 0; fhd_eor = 0; fhd_otas = OTA_NOP; fhd_cw1 = fhd_cw2 = fhd_buf = 0; -CLR_INT (INT_FHD); /* clear int, enb */ +CLR_INT (INT_FHD); /* clear int, enb */ CLR_ENB (INT_FHD); -sim_cancel (&fhd_unit); /* cancel operation */ +sim_cancel (&fhd_unit); /* cancel operation */ return SCPE_OK; } @@ -409,10 +438,11 @@ t_stat r; r = attach_unit (uptr, cptr); if (r != SCPE_OK) return r; if ((uptr->flags & UNIT_AUTO) && (sz = sim_fsize (uptr->fileref))) { - sf = (sz + ds_bytes - 1) / ds_bytes; - if (sf >= FH_NUMSF) sf = FH_NUMSF - 1; - uptr->flags = (uptr->flags & ~UNIT_SF) | - (sf << UNIT_V_SF); } + sf = (sz + ds_bytes - 1) / ds_bytes; + if (sf >= FH_NUMSF) sf = FH_NUMSF - 1; + uptr->flags = (uptr->flags & ~UNIT_SF) | + (sf << UNIT_V_SF); + } uptr->capac = UNIT_GETSF (uptr->flags) * FH_WDPSF; return SCPE_OK; } diff --git a/H316/h316_lp.c b/H316/h316_lp.c index a726c3ce..81834897 100644 --- a/H316/h316_lp.c +++ b/H316/h316_lp.c @@ -1,6 +1,6 @@ /* h316_lp.c: Honeywell 316/516 line printer - Copyright (c) 1999-2004, Robert M. Supnik + Copyright (c) 1999-2005, 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"), @@ -19,16 +19,16 @@ 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 + 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 + lpt line printer - 01-Dec-04 RMS Fixed bug in DMA/DMC support - 24-Oct-03 RMS Added DMA/DMC support - 25-Apr-03 RMS Revised for extended file support - 30-May-02 RMS Widened POS to 32b + 01-Dec-04 RMS Fixed bug in DMA/DMC support + 24-Oct-03 RMS Added DMA/DMC support + 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 @@ -52,54 +52,54 @@ 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_rdy transfer ready flag - lpt_prdn printing done flag - lpt_dma use DMA/DMC - lpt_eor DMA/DMC end of range + 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_rdy transfer ready flag + lpt_prdn printing done flag + lpt_dma use DMA/DMC + lpt_eor DMA/DMC end of range */ #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 */ +#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_int, dev_enb; extern int32 stop_inst; extern uint32 chan_req; -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_rdy = 0; /* transfer flag */ -int32 lpt_prdn = 1; /* printing done */ -int32 lpt_dma = 0; /* use DMA/DMC */ -int32 lpt_eor = 0; /* DMA/DMC end range */ -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 */ +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_rdy = 0; /* transfer flag */ +int32 lpt_prdn = 1; /* printing done */ +int32 lpt_dma = 0; /* use DMA/DMC */ +int32 lpt_eor = 0; /* DMA/DMC end range */ +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 */ int32 lptio (int32 inst, int32 fnc, int32 dat, int32 dev); 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 + lpt_dev LPT device descriptor + lpt_unit LPT unit descriptor + lpt_mod LPT modifiers + lpt_reg LPT register list */ DIB lpt_dib = { LPT, IOBUS, 1, &lptio }; @@ -107,138 +107,164 @@ DIB lpt_dib = { LPT, IOBUS, 1, &lptio }; 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 (RDY, lpt_rdy, 0) }, - { FLDATA (EOR, lpt_eor, 0) }, - { FLDATA (DMA, lpt_dma, 0) }, - { FLDATA (PRDN, lpt_prdn, 0) }, - { FLDATA (INTREQ, dev_int, INT_V_LPT) }, - { FLDATA (ENABLE, dev_enb, 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 } }; + { DRDATA (WDPOS, lpt_wdpos, 6) }, + { DRDATA (DRPOS, lpt_drpos, 6) }, + { FLDATA (CRPOS, lpt_crpos, 0) }, + { FLDATA (RDY, lpt_rdy, 0) }, + { FLDATA (EOR, lpt_eor, 0) }, + { FLDATA (DMA, lpt_dma, 0) }, + { FLDATA (PRDN, lpt_prdn, 0) }, + { FLDATA (INTREQ, dev_int, INT_V_LPT) }, + { FLDATA (ENABLE, dev_enb, 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, - &lpt_dib, DEV_DISABLE }; - + "LPT", &lpt_unit, lpt_reg, NULL, + 1, 10, 31, 1, 8, 8, + NULL, NULL, &lpt_reset, + NULL, NULL, NULL, + &lpt_dib, DEV_DISABLE + }; + /* IO routine */ int32 lptio (int32 inst, int32 fnc, int32 dat, int32 dev) { -int32 ch = lpt_dib.chan - 1; /* DMA/DMC chan */ +int32 ch = lpt_dib.chan - 1; /* DMA/DMC chan */ 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_INT (INT_LPT); /* clear int */ - break; - case 003: /* init scan DMA/DMC */ - lpt_prdn = 0; /* clear pr done */ - lpt_wdpos = 0; /* init scan pos */ - lpt_eor = 0; - if (ch >= 0) lpt_dma = 1; /* try for DMA/DMC */ - else lpt_dma = 0; - if (!sim_is_active (&lpt_unit)) { - lpt_rdy = 1; - if (lpt_dma) SET_CH_REQ (ch); } - CLR_INT (INT_LPT); /* clear int */ - break; - case 007: /* init scan IO bus */ - lpt_prdn = 0; /* clear pr done */ - lpt_wdpos = 0; /* init scan pos */ - lpt_eor = 0; - lpt_dma = 0; /* IO bus */ - if (!sim_is_active (&lpt_unit)) lpt_rdy = 1; - CLR_INT (INT_LPT); /* clear int */ - break; - default: - return IOBADFNC (dat); } - break; +switch (inst) { /* case on opcode */ -case ioSKS: /* SKS */ - switch (fnc) { /* case on fnc */ - case 000: /* if xfer rdy */ - if (lpt_rdy) 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 ioOCP: /* OCP */ + switch (fnc) { /* case on fnc */ -case ioOTA: /* OTA */ - if (fnc) return IOBADFNC (dat); /* only fnc 0 */ - if (lpt_rdy) { /* xfer ready? */ - lpt_rdy = 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; + 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_INT (INT_LPT); /* clear int */ + break; + + case 003: /* init scan DMA/DMC */ + lpt_prdn = 0; /* clear pr done */ + lpt_wdpos = 0; /* init scan pos */ + lpt_eor = 0; + if (ch >= 0) lpt_dma = 1; /* try for DMA/DMC */ + else lpt_dma = 0; + if (!sim_is_active (&lpt_unit)) { + lpt_rdy = 1; + if (lpt_dma) SET_CH_REQ (ch); + } + CLR_INT (INT_LPT); /* clear int */ + break; + + case 007: /* init scan IO bus */ + lpt_prdn = 0; /* clear pr done */ + lpt_wdpos = 0; /* init scan pos */ + lpt_eor = 0; + lpt_dma = 0; /* IO bus */ + if (!sim_is_active (&lpt_unit)) lpt_rdy = 1; + CLR_INT (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_rdy) 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_rdy) { /* xfer ready? */ + lpt_rdy = 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; + + case ioEND: /* end DMA/DMC */ + lpt_eor = 1; /* set end range */ + break; + } /* end case op */ -case ioEND: /* end DMA/DMC */ - lpt_eor = 1; /* set end range */ - break; } /* end case op */ return dat; } @@ -247,35 +273,40 @@ return dat; t_stat lpt_svc (UNIT *uptr) { int32 i; -int32 ch = lpt_dib.chan - 1; /* DMA/DMC chan */ +int32 ch = lpt_dib.chan - 1; /* DMA/DMC chan */ static const char *lpt_cc[] = { - "\r", - "\n", - "\n\f", - "\n" }; + "\r", + "\n", + "\n\f", + "\n" + }; -if ((lpt_unit.flags & UNIT_ATT) == 0) /* attached? */ - return IORETURN (lpt_stopioe, SCPE_UNATT); -if (lpt_dma) { /* DMA/DMC? */ - if (lpt_eor) SET_INT (INT_LPT); /* end range? intr */ - else { - lpt_rdy = 1; /* set ready */ - SET_CH_REQ (ch); } } /* get more data */ -else lpt_rdy = 1; /* IO, continue scan */ -if (lpt_dma && lpt_eor) SET_INT (INT_LPT); /* end of range? */ -if (lpt_svcst & LPT_SVCSH) { /* shuttling */ - SET_INT (INT_LPT); /* interrupt */ - if (lpt_crpos == 0) lpt_prdn = 1; } -if (lpt_svcst & LPT_SVCPA) { /* paper advance */ - SET_INT (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 */ - } +if ((lpt_unit.flags & UNIT_ATT) == 0) /* attached? */ + return IORETURN (lpt_stopioe, SCPE_UNATT); +if (lpt_dma) { /* DMA/DMC? */ + if (lpt_eor) SET_INT (INT_LPT); /* end range? intr */ + else { + lpt_rdy = 1; /* set ready */ + SET_CH_REQ (ch); /* get more data */ + } + } +else lpt_rdy = 1; /* IO, continue scan */ +if (lpt_dma && lpt_eor) SET_INT (INT_LPT); /* end of range? */ +if (lpt_svcst & LPT_SVCSH) { /* shuttling */ + SET_INT (INT_LPT); /* interrupt */ + if (lpt_crpos == 0) lpt_prdn = 1; + } +if (lpt_svcst & LPT_SVCPA) { /* paper advance */ + SET_INT (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; } @@ -286,16 +317,16 @@ 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_rdy = 0; /* not rdy to xfer */ -lpt_prdn = 1; /* printing done */ +lpt_wdpos = lpt_drpos = lpt_crpos = 0; /* clear positions */ +lpt_svcst = lpt_svcch = 0; /* idle state */ +lpt_rdy = 0; /* not rdy to xfer */ +lpt_prdn = 1; /* printing done */ lpt_eor = 0; lpt_dma = 0; -for (i = 0; i < LPT_WIDTH; i++) lpt_buf[i] = ' '; /* clear buffer */ +for (i = 0; i < LPT_WIDTH; i++) lpt_buf[i] = ' '; /* clear buffer */ lpt_buf[LPT_WIDTH] = 0; -CLR_INT (INT_LPT); /* clear int, enb */ +CLR_INT (INT_LPT); /* clear int, enb */ CLR_ENB (INT_LPT); -sim_cancel (&lpt_unit); /* deactivate unit */ +sim_cancel (&lpt_unit); /* deactivate unit */ return SCPE_OK; } diff --git a/H316/h316_mt.c b/H316/h316_mt.c index 1249a338..324f2433 100644 --- a/H316/h316_mt.c +++ b/H316/h316_mt.c @@ -19,25 +19,26 @@ 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 + 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 516-4100 seven track magnetic tape + mt 516-4100 seven track magnetic tape - 08-Feb-05 RMS Fixed error reporting from OCP (found by Philipp Hachtmann) - 01-Dec-04 RMS Fixed bug in DMA/DMC support + 26-Aug-05 RMS Revised to use API for write lock check + 08-Feb-05 RMS Fixed error reporting from OCP (found by Philipp Hachtmann) + 01-Dec-04 RMS Fixed bug in DMA/DMC 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 - 32b byte count + 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. @@ -46,57 +47,56 @@ #include "h316_defs.h" #include "sim_tape.h" -#define MT_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 */ -#define UNIT_WPRT (MTUF_WLK | UNIT_RO) /* write prot */ +#define MT_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 */ /* Function codes */ -#define FNC_RBCD2 000 -#define FNC_RBIN2 001 -#define FNC_RBIN3 002 -#define FNC_DMANM 003 -#define FNC_WBCD2 004 -#define FNC_WBIN2 005 -#define FNC_WEOF 006 -#define FNC_IOBUS 007 -#define FNC_WBIN3 010 -#define FNC_FSR 011 -#define FNC_FSF 012 -#define FNC_DMAAU 013 -#define FNC_REW 014 -#define FNC_BSR 015 -#define FNC_BSF 016 -#define FNC_STOPW 017 -#define FNC_2ND 020 /* second state */ -#define FNC_NOP (FNC_STOPW|FNC_2ND) -#define FNC_EOM 040 /* end of motion */ +#define FNC_RBCD2 000 +#define FNC_RBIN2 001 +#define FNC_RBIN3 002 +#define FNC_DMANM 003 +#define FNC_WBCD2 004 +#define FNC_WBIN2 005 +#define FNC_WEOF 006 +#define FNC_IOBUS 007 +#define FNC_WBIN3 010 +#define FNC_FSR 011 +#define FNC_FSF 012 +#define FNC_DMAAU 013 +#define FNC_REW 014 +#define FNC_BSR 015 +#define FNC_BSF 016 +#define FNC_STOPW 017 +#define FNC_2ND 020 /* second state */ +#define FNC_NOP (FNC_STOPW|FNC_2ND) +#define FNC_EOM 040 /* end of motion */ /* Status - unit.UST */ -#define STA_BOT 0000002 /* beg of tape */ -#define STA_EOT 0000001 /* end of tape */ - +#define STA_BOT 0000002 /* beg of tape */ +#define STA_EOT 0000001 /* end of tape */ + extern int32 dev_int, dev_enb, chan_req; extern int32 stop_inst; -uint32 mt_buf = 0; /* data buffer */ -uint32 mt_usel = 0; /* unit select */ -uint32 mt_busy = 0; /* ctlr busy */ -uint32 mt_mdirq = 0; /* motion done int req */ -uint32 mt_rdy = 0; /* transfer ready (int) */ -uint32 mt_err = 0; /* error */ -uint32 mt_eof = 0; /* end of file */ -uint32 mt_eor = 0; /* transfer done */ -uint32 mt_dma = 0; /* DMA/DMC */ -uint32 mt_xtime = 16; /* transfer time */ -uint32 mt_ctime = 3000; /* start/stop time */ -uint32 mt_stopioe = 1; /* stop on I/O error */ -uint8 mtxb[DBSIZE] = { 0 }; /* data buffer */ -t_mtrlnt mt_ptr = 0, mt_max = 0; /* buffer ptrs */ +uint32 mt_buf = 0; /* data buffer */ +uint32 mt_usel = 0; /* unit select */ +uint32 mt_busy = 0; /* ctlr busy */ +uint32 mt_mdirq = 0; /* motion done int req */ +uint32 mt_rdy = 0; /* transfer ready (int) */ +uint32 mt_err = 0; /* error */ +uint32 mt_eof = 0; /* end of file */ +uint32 mt_eor = 0; /* transfer done */ +uint32 mt_dma = 0; /* DMA/DMC */ +uint32 mt_xtime = 16; /* transfer time */ +uint32 mt_ctime = 3000; /* start/stop time */ +uint32 mt_stopioe = 1; /* stop on I/O error */ +uint8 mtxb[DBSIZE] = { 0 }; /* data buffer */ +t_mtrlnt mt_ptr = 0, mt_max = 0; /* buffer ptrs */ int32 mtio (int32 inst, int32 fnc, int32 dat, int32 dev); void mt_updint (uint32 rdy, uint32 mdone); @@ -106,174 +106,206 @@ t_stat mt_attach (UNIT *uptr, char *cptr); t_stat mt_detach (UNIT *uptr); t_stat mt_map_err (UNIT *uptr, t_stat st); void mt_wrwd (UNIT *uptr, uint32 dat); - + /* MT data structures - mt_dev MT device descriptor - mt_unit MT unit list - mt_reg MT register list - mt_mod MT modifier list + mt_dev MT device descriptor + mt_unit MT unit list + mt_reg MT register list + mt_mod MT modifier list */ DIB mt_dib = { MT, IOBUS, MT_NUMDR, &mtio }; UNIT mt_unit[] = { - { UDATA (&mt_svc, UNIT_ATTABLE + UNIT_ROABLE + UNIT_DISABLE, 0) }, - { UDATA (&mt_svc, UNIT_ATTABLE + UNIT_ROABLE + UNIT_DISABLE, 0) }, - { UDATA (&mt_svc, UNIT_ATTABLE + UNIT_ROABLE + UNIT_DISABLE, 0) }, - { UDATA (&mt_svc, UNIT_ATTABLE + UNIT_ROABLE + UNIT_DISABLE, 0) } }; + { UDATA (&mt_svc, UNIT_ATTABLE + UNIT_ROABLE + UNIT_DISABLE, 0) }, + { UDATA (&mt_svc, UNIT_ATTABLE + UNIT_ROABLE + UNIT_DISABLE, 0) }, + { UDATA (&mt_svc, UNIT_ATTABLE + UNIT_ROABLE + UNIT_DISABLE, 0) }, + { UDATA (&mt_svc, UNIT_ATTABLE + UNIT_ROABLE + UNIT_DISABLE, 0) } + }; REG mt_reg[] = { - { ORDATA (BUF, mt_buf, 16) }, - { ORDATA (USEL, mt_usel, 2) }, - { FLDATA (BUSY, mt_busy, 0) }, - { FLDATA (RDY, mt_rdy, 0) }, - { FLDATA (ERR, mt_err, 0) }, - { FLDATA (EOF, mt_eof, 0) }, - { FLDATA (EOR, mt_eor, 0) }, - { FLDATA (MDIRQ, mt_mdirq, 0) }, - { FLDATA (DMA, mt_dma, 0) }, - { FLDATA (INTREQ, dev_int, INT_V_MT) }, - { FLDATA (ENABLE, dev_enb, INT_V_MT) }, - { BRDATA (DBUF, mtxb, 8, 8, DBSIZE) }, - { DRDATA (BPTR, mt_ptr, DB_N_SIZE + 1) }, - { DRDATA (BMAX, mt_max, DB_N_SIZE + 1) }, - { DRDATA (CTIME, mt_ctime, 24), REG_NZ + PV_LEFT }, - { DRDATA (XTIME, mt_xtime, 24), REG_NZ + PV_LEFT }, - { URDATA (POS, mt_unit[0].pos, 10, T_ADDR_W, 0, MT_NUMDR, PV_LEFT) }, - { URDATA (FNC, mt_unit[0].FNC, 8, 8, 0, MT_NUMDR, REG_HRO) }, - { URDATA (UST, mt_unit[0].UST, 8, 2, 0, MT_NUMDR, REG_HRO) }, - { ORDATA (CHAN, mt_dib.chan, 5), REG_HRO }, - { FLDATA (STOP_IOE, mt_stopioe, 0) }, - { NULL } }; + { ORDATA (BUF, mt_buf, 16) }, + { ORDATA (USEL, mt_usel, 2) }, + { FLDATA (BUSY, mt_busy, 0) }, + { FLDATA (RDY, mt_rdy, 0) }, + { FLDATA (ERR, mt_err, 0) }, + { FLDATA (EOF, mt_eof, 0) }, + { FLDATA (EOR, mt_eor, 0) }, + { FLDATA (MDIRQ, mt_mdirq, 0) }, + { FLDATA (DMA, mt_dma, 0) }, + { FLDATA (INTREQ, dev_int, INT_V_MT) }, + { FLDATA (ENABLE, dev_enb, INT_V_MT) }, + { BRDATA (DBUF, mtxb, 8, 8, DBSIZE) }, + { DRDATA (BPTR, mt_ptr, DB_N_SIZE + 1) }, + { DRDATA (BMAX, mt_max, DB_N_SIZE + 1) }, + { DRDATA (CTIME, mt_ctime, 24), REG_NZ + PV_LEFT }, + { DRDATA (XTIME, mt_xtime, 24), REG_NZ + PV_LEFT }, + { URDATA (POS, mt_unit[0].pos, 10, T_ADDR_W, 0, MT_NUMDR, PV_LEFT) }, + { URDATA (FNC, mt_unit[0].FNC, 8, 8, 0, MT_NUMDR, REG_HRO) }, + { URDATA (UST, mt_unit[0].UST, 8, 2, 0, MT_NUMDR, REG_HRO) }, + { ORDATA (CHAN, mt_dib.chan, 5), REG_HRO }, + { 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, NULL, "IOBUS", - &io_set_iobus, NULL, NULL }, - { MTAB_XTD|MTAB_VDV, 0, NULL, "DMC", - &io_set_dmc, NULL, NULL }, - { MTAB_XTD|MTAB_VDV, 0, NULL, "DMA", - &io_set_dma, NULL, NULL }, - { MTAB_XTD|MTAB_VDV, 0, "CHANNEL", NULL, - NULL, &io_show_chan, NULL }, - { 0 } }; + { 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, "IOBUS", + &io_set_iobus, NULL, NULL }, + { MTAB_XTD|MTAB_VDV, 0, NULL, "DMC", + &io_set_dmc, NULL, NULL }, + { MTAB_XTD|MTAB_VDV, 0, NULL, "DMA", + &io_set_dma, NULL, NULL }, + { MTAB_XTD|MTAB_VDV, 0, "CHANNEL", NULL, + NULL, &io_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, - NULL, &mt_attach, &mt_detach, - &mt_dib, DEV_DISABLE }; - + "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 + }; + /* IO routine */ int32 mtio (int32 inst, int32 fnc, int32 dat, int32 dev) { uint32 u = dev & 03; UNIT *uptr = mt_dev.units + u; -static uint8 wrt_fnc[16] = { /* >0 = wr, 1 = chan op */ - 0, 0, 0, 0, 1, 1, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0 }; +static uint8 wrt_fnc[16] = { /* >0 = wr, 1 = chan op */ + 0, 0, 0, 0, 1, 1, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0 + }; + +switch (inst) { /* case on opcode */ + + case ioOCP: + mt_updint (mt_rdy, 0); /* clear motion intr */ + mt_eof = 0; /* clear eof */ + switch (fnc) { /* case on function */ + + case FNC_DMANM: /* set DMA/DMC */ + case FNC_DMAAU: + mt_usel = u; /* save unit select */ + if (mt_dib.chan) mt_dma = 1; /* set DMA if configured */ + else mt_dma = 0; + break; + + case FNC_IOBUS: /* set IOBUS */ + mt_usel = u; /* save unit select */ + mt_dma = 0; + break; + + case FNC_STOPW: /* stop write */ + mt_usel = u; /* save unit select */ + mt_updint (0, mt_mdirq); /* clear ready */ + if (wrt_fnc[uptr->FNC & 017] == 1) /* writing? */ + mt_eor = 1; /* set transfer done */ + break; + + default: /* motion command */ + if (mt_busy) return dat; /* nop if ctlr busy */ + mt_eor = 0; /* clr transfer done */ + mt_err = 0; /* clr error */ + mt_usel = u; /* save unit select */ + if ((uptr->flags & UNIT_ATT) == 0) /* not attached? */ + return (((mt_stopioe? SCPE_UNATT: SCPE_OK) << IOT_V_REASON) | dat); + if (sim_is_active (uptr)) return dat; /* nop if busy */ + if (wrt_fnc[fnc] && sim_tape_wrp (uptr)) + return ((STOP_MTWRP << IOT_V_REASON) | dat); + uptr->FNC = fnc; + uptr->UST = 0; + mt_busy = 1; + sim_activate (uptr, mt_ctime); /* schedule */ + break; + } + break; + + case ioINA: /* INA */ + if (fnc) return IOBADFNC (dat); /* fnc 0 only */ + if (mt_rdy) { /* ready? */ + mt_rdy = 0; /* clear ready */ + return IOSKIP (dat | mt_buf); /* ret buf, skip */ + } + break; + + case ioOTA: /* OTA */ + if (fnc) return IOBADFNC (dat); /* fnc 0 only */ + if (mt_rdy) { /* ready? */ + mt_rdy = 0; /* clear ready */ + mt_buf = dat; /* store buf */ + return IOSKIP (dat); /* skip */ + } + break; + + case ioSKS: + uptr = mt_dev.units + mt_usel; /* use saved unit sel */ + switch (fnc) { + + case 000: /* ready */ + if (mt_rdy) return IOSKIP (dat); + break; + + case 001: /* !busy */ + if (!mt_busy) return IOSKIP (dat); + break; + + case 002: /* !error */ + if (!mt_err) return IOSKIP (dat); + break; + + case 003: /* !BOT */ + if (!(uptr->UST & STA_BOT)) return IOSKIP (dat); + break; + + case 004: /* !interrupting */ + if (!TST_INTREQ (INT_MT)) return IOSKIP (dat); + break; + + case 005: /* !EOT */ + if (!(uptr->UST & STA_EOT)) return IOSKIP (dat); + break; + + case 006: /* !EOF */ + if (!mt_eof) return IOSKIP (dat); + break; + + case 007: /* !write prot */ + if (!sim_tape_wrp (uptr)) return IOSKIP (dat); + break; + + case 011: /* operational */ + if ((uptr->flags & UNIT_ATT) && + ((uptr->FNC & 017) != FNC_REW)) return IOSKIP (dat); + break; + + case 012: /* skip if !chan 2 */ + return IOSKIP (dat); + + case 013: /* skip if !auto */ + return IOSKIP (dat); + + case 014: /* !rewinding */ + uptr = mt_dev.units + (dev & 03); /* use specified unit */ + if ((uptr->FNC & 017) != FNC_REW) return IOSKIP (dat); + break; + } + break; + + case ioEND: /* end of range */ + mt_eor = 1; /* transfer done */ + break; + } -switch (inst) { /* case on opcode */ -case ioOCP: - mt_updint (mt_rdy, 0); /* clear motion intr */ - mt_eof = 0; /* clear eof */ - switch (fnc) { /* case on function */ - case FNC_DMANM: /* set DMA/DMC */ - case FNC_DMAAU: - mt_usel = u; /* save unit select */ - if (mt_dib.chan) mt_dma = 1; /* set DMA if configured */ - else mt_dma = 0; - break; - case FNC_IOBUS: /* set IOBUS */ - mt_usel = u; /* save unit select */ - mt_dma = 0; - break; - case FNC_STOPW: /* stop write */ - mt_usel = u; /* save unit select */ - mt_updint (0, mt_mdirq); /* clear ready */ - if (wrt_fnc[uptr->FNC & 017] == 1) /* writing? */ - mt_eor = 1; /* set transfer done */ - break; - default: /* motion command */ - if (mt_busy) return dat; /* nop if ctlr busy */ - mt_eor = 0; /* clr transfer done */ - mt_err = 0; /* clr error */ - mt_usel = u; /* save unit select */ - if ((uptr->flags & UNIT_ATT) == 0) /* not attached? */ - return (((mt_stopioe? SCPE_UNATT: SCPE_OK) << IOT_V_REASON) | dat); - if (sim_is_active (uptr)) return dat; /* nop if busy */ - if (wrt_fnc[fnc] && (uptr->flags & UNIT_WPRT)) - return ((STOP_MTWRP << IOT_V_REASON) | dat); - uptr->FNC = fnc; - uptr->UST = 0; - mt_busy = 1; - sim_activate (uptr, mt_ctime); /* schedule */ - break; } - break; -case ioINA: /* INA */ - if (fnc) return IOBADFNC (dat); /* fnc 0 only */ - if (mt_rdy) { /* ready? */ - mt_rdy = 0; /* clear ready */ - return IOSKIP (dat | mt_buf); } /* ret buf, skip */ - break; -case ioOTA: /* OTA */ - if (fnc) return IOBADFNC (dat); /* fnc 0 only */ - if (mt_rdy) { /* ready? */ - mt_rdy = 0; /* clear ready */ - mt_buf = dat; /* store buf */ - return IOSKIP (dat); } /* skip */ - break; -case ioSKS: - uptr = mt_dev.units + mt_usel; /* use saved unit sel */ - switch (fnc) { - case 000: /* ready */ - if (mt_rdy) return IOSKIP (dat); - break; - case 001: /* !busy */ - if (!mt_busy) return IOSKIP (dat); - break; - case 002: /* !error */ - if (!mt_err) return IOSKIP (dat); - break; - case 003: /* !BOT */ - if (!(uptr->UST & STA_BOT)) return IOSKIP (dat); - break; - case 004: /* !interrupting */ - if (!TST_INTREQ (INT_MT)) return IOSKIP (dat); - break; - case 005: /* !EOT */ - if (!(uptr->UST & STA_EOT)) return IOSKIP (dat); - break; - case 006: /* !EOF */ - if (!mt_eof) return IOSKIP (dat); - break; - case 007: /* !write prot */ - if (!(uptr->flags & UNIT_WPRT)) return IOSKIP (dat); - break; - case 011: /* operational */ - if ((uptr->flags & UNIT_ATT) && - ((uptr->FNC & 017) != FNC_REW)) return IOSKIP (dat); - break; - case 012: /* skip if !chan 2 */ - return IOSKIP (dat); - case 013: /* skip if !auto */ - return IOSKIP (dat); - case 014: /* !rewinding */ - uptr = mt_dev.units + (dev & 03); /* use specified unit */ - if ((uptr->FNC & 017) != FNC_REW) return IOSKIP (dat); - break; } - break; -case ioEND: /* end of range */ - mt_eor = 1; /* transfer done */ - break; } return dat; } - + /* Unit service If rewind done, reposition to start of tape, set status @@ -284,150 +316,159 @@ return dat; t_stat mt_svc (UNIT *uptr) { -int32 ch = mt_dib.chan - 1; /* DMA/DMC ch */ +int32 ch = mt_dib.chan - 1; /* DMA/DMC ch */ uint32 i, c1, c2, c3; t_mtrlnt tbc; t_stat st, r = SCPE_OK; -if ((uptr->flags & UNIT_ATT) == 0) { /* offline? */ - mt_err = 1; - mt_busy = 0; - mt_updint (0, 1); /* cmd done */ - return IORETURN (mt_stopioe, SCPE_UNATT); } +if ((uptr->flags & UNIT_ATT) == 0) { /* offline? */ + mt_err = 1; + mt_busy = 0; + mt_updint (0, 1); /* cmd done */ + return IORETURN (mt_stopioe, SCPE_UNATT); + } -switch (uptr->FNC) { /* case on function */ -case FNC_REW: /* rewind (initial) */ - mt_busy = 0; /* ctlr not busy */ - uptr->FNC = uptr->FNC | FNC_2ND; - sim_activate (uptr, mt_ctime); - return SCPE_OK; /* continue */ +switch (uptr->FNC) { /* case on function */ -case FNC_REW | FNC_2ND: /* rewind done */ - uptr->pos = 0; /* reposition file */ - uptr->UST = STA_BOT; /* set BOT */ - uptr->FNC = FNC_NOP; /* nop function */ - for (i = 0; i < MT_NUMDR; i++) { /* last rewind? */ - if ((mt_unit[i].FNC & 017) == FNC_REW) return SCPE_OK; } - mt_updint (mt_rdy, 1); /* yes, motion done */ - return SCPE_OK; + case FNC_REW: /* rewind (initial) */ + mt_busy = 0; /* ctlr not busy */ + uptr->FNC = uptr->FNC | FNC_2ND; + sim_activate (uptr, mt_ctime); + return SCPE_OK; /* continue */ -case FNC_WEOF: /* write file mark */ - if (st = sim_tape_wrtmk (uptr)) /* write tmk, err? */ - r = mt_map_err (uptr, st); /* map error */ - break; /* sched end motion */ + case FNC_REW | FNC_2ND: /* rewind done */ + uptr->pos = 0; /* reposition file */ + uptr->UST = STA_BOT; /* set BOT */ + uptr->FNC = FNC_NOP; /* nop function */ + for (i = 0; i < MT_NUMDR; i++) { /* last rewind? */ + if ((mt_unit[i].FNC & 017) == FNC_REW) return SCPE_OK; + } + mt_updint (mt_rdy, 1); /* yes, motion done */ + return SCPE_OK; -case FNC_FSR: /* space fwd rec */ - if (st = sim_tape_sprecf (uptr, &tbc)) /* space fwd, err? */ - r = mt_map_err (uptr, st); /* map error */ - break; /* sched end motion */ + case FNC_WEOF: /* write file mark */ + if (st = sim_tape_wrtmk (uptr)) /* write tmk, err? */ + r = mt_map_err (uptr, st); /* map error */ + break; /* sched end motion */ -case FNC_BSR: /* space rev rec */ - if (st = sim_tape_sprecr (uptr, &tbc)) /* space rev, err? */ - r = mt_map_err (uptr, st); /* map error */ - break; /* sched end motion */ + case FNC_FSR: /* space fwd rec */ + if (st = sim_tape_sprecf (uptr, &tbc)) /* space fwd, err? */ + r = mt_map_err (uptr, st); /* map error */ + break; /* sched end motion */ -case FNC_FSF: /* space fwd file */ - while ((st = sim_tape_sprecf (uptr, &tbc)) == MTSE_OK) ; - r = mt_map_err (uptr, st); /* map error */ - break; /* sched end motion */ + case FNC_BSR: /* space rev rec */ + if (st = sim_tape_sprecr (uptr, &tbc)) /* space rev, err? */ + r = mt_map_err (uptr, st); /* map error */ + break; /* sched end motion */ -case FNC_BSF: /* space rev file */ - while ((st = sim_tape_sprecr (uptr, &tbc)) == MTSE_OK) ; - r = mt_map_err (uptr, st); /* map error */ - break; /* sched end motion */ + case FNC_FSF: /* space fwd file */ + while ((st = sim_tape_sprecf (uptr, &tbc)) == MTSE_OK) ; + r = mt_map_err (uptr, st); /* map error */ + break; /* sched end motion */ -case FNC_EOM: /* end of motion */ - uptr->FNC = FNC_NOP; /* nop function */ - mt_busy = 0; /* not busy */ - mt_updint (mt_rdy, 1); /* end of motion */ - return SCPE_OK; /* done! */ - -/* Unit service, continued */ + case FNC_BSF: /* space rev file */ + while ((st = sim_tape_sprecr (uptr, &tbc)) == MTSE_OK) ; + r = mt_map_err (uptr, st); /* map error */ + break; /* sched end motion */ -case FNC_RBCD2: case FNC_RBIN2: case FNC_RBIN3: /* read first */ - mt_ptr = 0; /* clr buf ptr */ - st = sim_tape_rdrecf (uptr, mtxb, &mt_max, DBSIZE); /* read rec */ - if (st != MTSE_OK) { /* error? */ - r = mt_map_err (uptr, st); /* map error */ - break; } /* sched end motion */ - uptr->FNC = uptr->FNC | FNC_2ND; /* next state */ - sim_activate (uptr, mt_xtime); /* sched xfer */ - return SCPE_OK; + case FNC_EOM: /* end of motion */ + uptr->FNC = FNC_NOP; /* nop function */ + mt_busy = 0; /* not busy */ + mt_updint (mt_rdy, 1); /* end of motion */ + return SCPE_OK; /* done! */ -case FNC_RBCD2 | FNC_2ND: /* read, word */ -case FNC_RBIN2 | FNC_2ND: -case FNC_RBIN3 | FNC_2ND: - if (mt_ptr >= mt_max) break; /* record done? */ - c1 = mtxb[mt_ptr++] & 077; /* get 2 chars */ - c2 = mtxb[mt_ptr++] & 077; - if (uptr->FNC == (FNC_RBCD2 | FNC_2ND)) { /* BCD? */ - if (c1 == 012) c1 = 0; /* change 12 to 0 */ - if (c2 == 012) c2 = 0; } - if (uptr->FNC == (FNC_RBIN3 | FNC_2ND)) { /* read 3? */ - if (mt_ptr >= mt_max) break; /* lose wd if not enuf */ - c3 = mtxb[mt_ptr++] & 017; } /* get 3rd char */ - else c3 = 0; - sim_activate (uptr, mt_xtime); /* no, sched word */ - if (mt_eor) return SCPE_OK; /* xfer done? */ - mt_buf = (c1 << 10) | (c2 << 4) | c3; /* pack chars */ - if (mt_rdy) mt_err = 1; /* buf full? err */ - mt_updint (1, mt_mdirq); /* set ready */ - if (mt_dma) SET_CH_REQ (ch); /* DMC/DMA? req chan */ - return SCPE_OK; /* continue */ - -case FNC_WBCD2: case FNC_WBIN2: case FNC_WBIN3: /* write first */ - mt_ptr = 0; /* clear buf ptr */ - mt_updint (1, mt_mdirq); /* set ready */ - if (mt_dma) SET_CH_REQ (ch); /* DMC/DMA? req chan */ - uptr->FNC = uptr->FNC | FNC_2ND; /* next state */ - sim_activate (uptr, mt_xtime); /* sched xfer */ - return SCPE_OK; /* continue */ + case FNC_RBCD2: case FNC_RBIN2: case FNC_RBIN3: /* read first */ + mt_ptr = 0; /* clr buf ptr */ + st = sim_tape_rdrecf (uptr, mtxb, &mt_max, DBSIZE); /* read rec */ + if (st != MTSE_OK) { /* error? */ + r = mt_map_err (uptr, st); /* map error */ + break; /* sched end motion */ + } + uptr->FNC = uptr->FNC | FNC_2ND; /* next state */ + sim_activate (uptr, mt_xtime); /* sched xfer */ + return SCPE_OK; -case FNC_WBCD2 | FNC_2ND: /* write, word */ -case FNC_WBIN2 | FNC_2ND: -case FNC_WBIN3 | FNC_2ND: - if (mt_eor || mt_rdy) { /* done or no data? */ - if (!mt_rdy) mt_wrwd (uptr, mt_buf); /* write last word */ - if (mt_ptr) { /* any data? */ - if (st = sim_tape_wrrecf (uptr, mtxb, mt_ptr)) /* write, err? */ - r = mt_map_err (uptr, st); } /* map error */ - break; } /* sched end motion */ - mt_wrwd (uptr, mt_buf); /* write word */ - sim_activate (uptr, mt_xtime); /* no, sched word */ - mt_updint (1, mt_mdirq); /* set ready */ - if (mt_dma) SET_CH_REQ (ch); /* DMC/DMA? req chan */ - return SCPE_OK; /* continue */ + case FNC_RBCD2 | FNC_2ND: /* read, word */ + case FNC_RBIN2 | FNC_2ND: + case FNC_RBIN3 | FNC_2ND: + if (mt_ptr >= mt_max) break; /* record done? */ + c1 = mtxb[mt_ptr++] & 077; /* get 2 chars */ + c2 = mtxb[mt_ptr++] & 077; + if (uptr->FNC == (FNC_RBCD2 | FNC_2ND)) { /* BCD? */ + if (c1 == 012) c1 = 0; /* change 12 to 0 */ + if (c2 == 012) c2 = 0; + } + if (uptr->FNC == (FNC_RBIN3 | FNC_2ND)) { /* read 3? */ + if (mt_ptr >= mt_max) break; /* lose wd if not enuf */ + c3 = mtxb[mt_ptr++] & 017; /* get 3rd char */ + } + else c3 = 0; + sim_activate (uptr, mt_xtime); /* no, sched word */ + if (mt_eor) return SCPE_OK; /* xfer done? */ + mt_buf = (c1 << 10) | (c2 << 4) | c3; /* pack chars */ + if (mt_rdy) mt_err = 1; /* buf full? err */ + mt_updint (1, mt_mdirq); /* set ready */ + if (mt_dma) SET_CH_REQ (ch); /* DMC/DMA? req chan */ + return SCPE_OK; /* continue */ + + case FNC_WBCD2: case FNC_WBIN2: case FNC_WBIN3: /* write first */ + mt_ptr = 0; /* clear buf ptr */ + mt_updint (1, mt_mdirq); /* set ready */ + if (mt_dma) SET_CH_REQ (ch); /* DMC/DMA? req chan */ + uptr->FNC = uptr->FNC | FNC_2ND; /* next state */ + sim_activate (uptr, mt_xtime); /* sched xfer */ + return SCPE_OK; /* continue */ -default: /* unknown */ - break; } + case FNC_WBCD2 | FNC_2ND: /* write, word */ + case FNC_WBIN2 | FNC_2ND: + case FNC_WBIN3 | FNC_2ND: + if (mt_eor || mt_rdy) { /* done or no data? */ + if (!mt_rdy) mt_wrwd (uptr, mt_buf); /* write last word */ + if (mt_ptr) { /* any data? */ + if (st = sim_tape_wrrecf (uptr, mtxb, mt_ptr)) /* write, err? */ + r = mt_map_err (uptr, st); /* map error */ + } + break; /* sched end motion */ + } + mt_wrwd (uptr, mt_buf); /* write word */ + sim_activate (uptr, mt_xtime); /* no, sched word */ + mt_updint (1, mt_mdirq); /* set ready */ + if (mt_dma) SET_CH_REQ (ch); /* DMC/DMA? req chan */ + return SCPE_OK; /* continue */ + + default: /* unknown */ + break; + } /* End of command, process error or schedule end of motion */ if (r != SCPE_OK) { - uptr->FNC = FNC_NOP; /* nop function */ - mt_busy = 0; /* not busy */ - mt_updint (mt_rdy, 1); /* end of motion */ - return r; } -uptr->FNC = FNC_EOM; /* sched end motion */ + uptr->FNC = FNC_NOP; /* nop function */ + mt_busy = 0; /* not busy */ + mt_updint (mt_rdy, 1); /* end of motion */ + return r; + } +uptr->FNC = FNC_EOM; /* sched end motion */ sim_activate (uptr, mt_ctime); return SCPE_OK; } - + /* Write word to buffer */ void mt_wrwd (UNIT *uptr, uint32 dat) { uint32 c1, c2; -c1 = (dat >> 10) & 077; /* get 2 chars */ +c1 = (dat >> 10) & 077; /* get 2 chars */ c2 = (dat >> 4) & 077; -if (uptr->FNC == (FNC_WBCD2 | FNC_2ND)) { /* BCD? */ - if (c1 == 0) c1 = 012; /* change 0 to 12 */ - if (c2 == 0) c2 = 012; } -if (mt_ptr < DBSIZE) mtxb[mt_ptr++] = c1; /* store 2 char */ +if (uptr->FNC == (FNC_WBCD2 | FNC_2ND)) { /* BCD? */ + if (c1 == 0) c1 = 012; /* change 0 to 12 */ + if (c2 == 0) c2 = 012; + } +if (mt_ptr < DBSIZE) mtxb[mt_ptr++] = c1; /* store 2 char */ if (mt_ptr < DBSIZE) mtxb[mt_ptr++] = c2; -if ((uptr->FNC == (FNC_WBIN3 | FNC_2ND)) && /* write 3? */ - (mt_ptr < DBSIZE)) mtxb[mt_ptr++] = mt_buf & 017; +if ((uptr->FNC == (FNC_WBIN3 | FNC_2ND)) && /* write 3? */ + (mt_ptr < DBSIZE)) mtxb[mt_ptr++] = mt_buf & 017; return; } @@ -436,31 +477,40 @@ return; t_stat mt_map_err (UNIT *uptr, t_stat st) { switch (st) { -case MTSE_FMT: /* illegal fmt */ -case MTSE_UNATT: /* unattached */ - mt_err = 1; /* reject */ -case MTSE_OK: /* no error */ - return SCPE_IERR; /* never get here! */ -case MTSE_TMK: /* end of file */ - mt_eof = 1; /* eof */ - break; -case MTSE_INVRL: /* invalid rec lnt */ - mt_err = 1; - return SCPE_MTRLNT; -case MTSE_IOERR: /* IO error */ - mt_err = 1; /* error */ - if (mt_stopioe) return SCPE_IOERR; - break; -case MTSE_RECE: /* record in error */ -case MTSE_EOM: /* end of medium */ - mt_err = 1; /* error */ - break; -case MTSE_BOT: /* reverse into BOT */ - uptr->UST = STA_BOT; /* set status */ - break; -case MTSE_WRP: /* write protect */ - mt_err = 1; /* error */ - return STOP_MTWRP; } + + case MTSE_FMT: /* illegal fmt */ + case MTSE_UNATT: /* unattached */ + mt_err = 1; /* reject */ + case MTSE_OK: /* no error */ + return SCPE_IERR; /* never get here! */ + + case MTSE_TMK: /* end of file */ + mt_eof = 1; /* eof */ + break; + + case MTSE_INVRL: /* invalid rec lnt */ + mt_err = 1; + return SCPE_MTRLNT; + + case MTSE_IOERR: /* IO error */ + mt_err = 1; /* error */ + if (mt_stopioe) return SCPE_IOERR; + break; + + case MTSE_RECE: /* record in error */ + case MTSE_EOM: /* end of medium */ + mt_err = 1; /* error */ + break; + + case MTSE_BOT: /* reverse into BOT */ + uptr->UST = STA_BOT; /* set status */ + break; + + case MTSE_WRP: /* write protect */ + mt_err = 1; /* error */ + return STOP_MTWRP; + } + return SCPE_OK; } @@ -468,13 +518,13 @@ return SCPE_OK; void mt_updint (uint32 rdy, uint32 mdirq) { -mt_rdy = rdy; /* store new ready */ -mt_mdirq = mdirq; /* store new motion irq */ -if ((mt_rdy && !mt_dma) || mt_mdirq) SET_INT (INT_MT); /* update int request */ +mt_rdy = rdy; /* store new ready */ +mt_mdirq = mdirq; /* store new motion irq */ +if ((mt_rdy && !mt_dma) || mt_mdirq) SET_INT (INT_MT); /* update int request */ else CLR_INT (INT_MT); return; } - + /* Reset routine */ t_stat mt_reset (DEVICE *dptr) @@ -482,7 +532,7 @@ t_stat mt_reset (DEVICE *dptr) int32 i; UNIT *uptr; -mt_buf = 0; /* clear state */ +mt_buf = 0; /* clear state */ mt_usel = 0; mt_mdirq = 0; mt_eor = 0; @@ -491,14 +541,15 @@ mt_rdy = 0; mt_eof = 0; mt_err = 0; mt_dma = 0; -CLR_INT (INT_MT); /* clear int, enb */ +CLR_INT (INT_MT); /* clear int, enb */ CLR_ENB (INT_MT); -for (i = 0; i < MT_NUMDR; i++) { /* loop thru units */ - uptr = mt_dev.units + i; - sim_tape_reset (uptr); /* reset tape */ - sim_cancel (uptr); /* cancel op */ - uptr->UST = uptr->pos? 0: STA_BOT; /* update status */ - uptr->FNC = FNC_NOP; } +for (i = 0; i < MT_NUMDR; i++) { /* loop thru units */ + uptr = mt_dev.units + i; + sim_tape_reset (uptr); /* reset tape */ + sim_cancel (uptr); /* cancel op */ + uptr->UST = uptr->pos? 0: STA_BOT; /* update status */ + uptr->FNC = FNC_NOP; + } return SCPE_OK; } @@ -508,8 +559,8 @@ t_stat mt_attach (UNIT *uptr, char *cptr) { t_stat r; -r = sim_tape_attach (uptr, cptr); /* attach unit */ -if (r != SCPE_OK) return r; /* update status */ +r = sim_tape_attach (uptr, cptr); /* attach unit */ +if (r != SCPE_OK) return r; /* update status */ uptr->UST = STA_BOT; return r; } @@ -518,7 +569,7 @@ return r; t_stat mt_detach (UNIT* uptr) { -uptr->UST = 0; /* update status */ -uptr->FNC = FNC_NOP; /* nop function */ -return sim_tape_detach (uptr); /* detach unit */ +uptr->UST = 0; /* update status */ +uptr->FNC = FNC_NOP; /* nop function */ +return sim_tape_detach (uptr); /* detach unit */ } diff --git a/H316/h316_stddev.c b/H316/h316_stddev.c index 30419fac..f675aaf6 100644 --- a/H316/h316_stddev.c +++ b/H316/h316_stddev.c @@ -19,31 +19,31 @@ 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 + 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 + 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 - 05-Feb-05 RMS Fixed bug in OCP '0001 (found by Philipp Hachtmann) - 31-Jan-05 RMS Fixed bug in TTY print (found by Philipp Hachtmann) - 01-Dec-04 RMS Fixed problem in SKS '104 (reported by Philipp Hachtmann) - Fixed bug in SKS '504 - Added PTR detach routine, stops motion - Added PTR/PTP ASCII file support - Added TTR/TTP support - 24-Oct-03 RMS Added DMA/DMC support - 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 + 05-Feb-05 RMS Fixed bug in OCP '0001 (found by Philipp Hachtmann) + 31-Jan-05 RMS Fixed bug in TTY print (found by Philipp Hachtmann) + 01-Dec-04 RMS Fixed problem in SKS '104 (reported by Philipp Hachtmann) + Fixed bug in SKS '504 + Added PTR detach routine, stops motion + Added PTR/PTP ASCII file support + Added TTR/TTP support + 24-Oct-03 RMS Added DMA/DMC support + 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 The ASR-33/35 reader/punch logic, and the ASCII file support for all paper tape devices, logic is taken, with grateful thanks, from Adrian Wise's H316 emulator. @@ -66,31 +66,31 @@ #include "h316_defs.h" #include -#define CHAR_FLAG(c) (1u << (c)) +#define CHAR_FLAG(c) (1u << (c)) -#define BEL_FLAG CHAR_FLAG('\a') -#define LF_FLAG CHAR_FLAG('\n') -#define CR_FLAG CHAR_FLAG('\r') -#define HT_FLAG CHAR_FLAG('\t') +#define BEL_FLAG CHAR_FLAG('\a') +#define LF_FLAG CHAR_FLAG('\n') +#define CR_FLAG CHAR_FLAG('\r') +#define HT_FLAG CHAR_FLAG('\t') -#define CNTL_SET (BEL_FLAG | HT_FLAG | LF_FLAG | CR_FLAG) +#define CNTL_SET (BEL_FLAG | HT_FLAG | LF_FLAG | CR_FLAG) -#define UNIT_V_8B (UNIT_V_UF + 0) /* 8B */ -#define UNIT_V_KSR (UNIT_V_UF + 1) /* KSR33 */ -#define UNIT_V_ASC (UNIT_V_UF + 2) /* ASCII */ -#define UNIT_V_UASC (UNIT_V_UF + 3) /* Unix ASCII */ -#define UNIT_8B (1 << UNIT_V_8B) -#define UNIT_KSR (1 << UNIT_V_KSR) -#define UNIT_ASC (1 << UNIT_V_ASC) -#define UNIT_UASC (1 << UNIT_V_UASC) -#define STA u3 /* state bits */ -#define LF_PEND 01 /* lf pending */ -#define RUNNING 02 /* tape running */ +#define UNIT_V_8B (UNIT_V_UF + 0) /* 8B */ +#define UNIT_V_KSR (UNIT_V_UF + 1) /* KSR33 */ +#define UNIT_V_ASC (UNIT_V_UF + 2) /* ASCII */ +#define UNIT_V_UASC (UNIT_V_UF + 3) /* Unix ASCII */ +#define UNIT_8B (1 << UNIT_V_8B) +#define UNIT_KSR (1 << UNIT_V_KSR) +#define UNIT_ASC (1 << UNIT_V_ASC) +#define UNIT_UASC (1 << UNIT_V_UASC) +#define STA u3 /* state bits */ +#define LF_PEND 01 /* lf pending */ +#define RUNNING 02 /* tape running */ -#define XON 0021 -#define TAPE 0022 -#define XOFF 0023 -#define RUBOUT 0377 +#define XON 0021 +#define TAPE 0022 +#define XOFF 0023 +#define RUBOUT 0377 extern uint16 M[]; extern int32 PC; @@ -100,18 +100,18 @@ extern int32 dev_int, dev_enb; extern int32 sim_switches; extern UNIT cpu_unit; -uint32 ptr_motion = 0; /* read motion */ -uint32 ptr_stopioe = 0; /* stop on error */ +uint32 ptr_motion = 0; /* read motion */ +uint32 ptr_stopioe = 0; /* stop on error */ uint32 ptp_stopioe = 0; -uint32 ptp_power = 0; /* punch power, time */ +uint32 ptp_power = 0; /* punch power, time */ int32 ptp_ptime; uint32 ttr_stopioe = 0; -uint32 tty_mode = 0; /* input (0), output (1) */ -uint32 tty_buf = 0; /* tty buffer */ +uint32 tty_mode = 0; /* input (0), output (1) */ +uint32 tty_buf = 0; /* tty buffer */ uint32 ttr_xoff_read = 0; uint32 ttp_tape_rcvd = 0; uint32 ttp_xoff_rcvd = 0; -int32 clk_tps = 60; /* ticks per second */ +int32 clk_tps = 60; /* ticks per second */ int32 ptrio (int32 inst, int32 fnc, int32 dat, int32 dev); t_stat ptr_svc (UNIT *uptr); @@ -136,198 +136,217 @@ t_stat pt_attach (UNIT *uptr, char *cptr); t_stat pt_detach (UNIT *uptr); t_stat tto_write (int32 c); t_stat ttp_write (int32 c); - + /* PTR data structures - ptr_dev PTR device descriptor - ptr_unit PTR unit descriptor - ptr_mod PTR modifiers - ptr_reg PTR register list + ptr_dev PTR device descriptor + ptr_unit PTR unit descriptor + ptr_mod PTR modifiers + ptr_reg PTR register list */ DIB ptr_dib = { PTR, IOBUS, 1, &ptrio }; UNIT ptr_unit = { - UDATA (&ptr_svc, UNIT_SEQ+UNIT_ATTABLE+UNIT_ROABLE, 0), - SERIAL_IN_WAIT }; + 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_int, INT_V_PTR) }, - { FLDATA (ENABLE, dev_enb, INT_V_PTR) }, - { FLDATA (MOTION, ptr_motion, 0) }, - { DRDATA (POS, ptr_unit.pos, T_ADDR_W), PV_LEFT }, - { DRDATA (TIME, ptr_unit.wait, 24), PV_LEFT }, - { ORDATA (RSTATE, ptr_unit.STA, 2), REG_HIDDEN }, - { FLDATA (STOP_IOE, ptr_stopioe, 0) }, - { NULL } }; + { ORDATA (BUF, ptr_unit.buf, 8) }, + { FLDATA (READY, dev_int, INT_V_PTR) }, + { FLDATA (ENABLE, dev_enb, INT_V_PTR) }, + { FLDATA (MOTION, ptr_motion, 0) }, + { DRDATA (POS, ptr_unit.pos, T_ADDR_W), PV_LEFT }, + { DRDATA (TIME, ptr_unit.wait, 24), PV_LEFT }, + { ORDATA (RSTATE, ptr_unit.STA, 2), REG_HIDDEN }, + { FLDATA (STOP_IOE, ptr_stopioe, 0) }, + { NULL } + }; MTAB pt_mod[] = { - { UNIT_ATT+UNIT_ASC+UNIT_UASC, UNIT_ATT+UNIT_ASC, "ASCII", NULL }, - { UNIT_ATT+UNIT_ASC+UNIT_UASC, UNIT_ATT+UNIT_ASC+UNIT_UASC, "Unix ASCII", NULL }, - { 0 } }; + { UNIT_ATT+UNIT_ASC+UNIT_UASC, UNIT_ATT+UNIT_ASC, "ASCII", NULL }, + { UNIT_ATT+UNIT_ASC+UNIT_UASC, UNIT_ATT+UNIT_ASC+UNIT_UASC, "Unix ASCII", NULL }, + { 0 } + }; DEVICE ptr_dev = { - "PTR", &ptr_unit, ptr_reg, pt_mod, - 1, 10, 31, 1, 8, 8, - NULL, NULL, &ptr_reset, - &ptr_boot, &pt_attach, &pt_detach, - &ptr_dib, 0 }; + "PTR", &ptr_unit, ptr_reg, pt_mod, + 1, 10, 31, 1, 8, 8, + NULL, NULL, &ptr_reset, + &ptr_boot, &pt_attach, &pt_detach, + &ptr_dib, 0 + }; /* PTP data structures - ptp_dev PTP device descriptor - ptp_unit PTP unit descriptor - ptp_mod PTP modifiers - ptp_reg PTP register list + ptp_dev PTP device descriptor + ptp_unit PTP unit descriptor + ptp_mod PTP modifiers + ptp_reg PTP register list */ DIB ptp_dib = { PTP, IOBUS, 1, &ptpio }; UNIT ptp_unit = { - UDATA (&ptp_svc, UNIT_SEQ+UNIT_ATTABLE, 0), SERIAL_OUT_WAIT }; + UDATA (&ptp_svc, UNIT_SEQ+UNIT_ATTABLE, 0), SERIAL_OUT_WAIT + }; REG ptp_reg[] = { - { ORDATA (BUF, ptp_unit.buf, 8) }, - { FLDATA (READY, dev_int, INT_V_PTP) }, - { FLDATA (ENABLE, dev_enb, INT_V_PTP) }, - { FLDATA (POWER, ptp_power, 0) }, - { DRDATA (POS, ptp_unit.pos, T_ADDR_W), PV_LEFT }, - { ORDATA (PSTATE, ptp_unit.STA, 2), REG_HIDDEN }, - { DRDATA (TIME, ptp_unit.wait, 24), PV_LEFT }, - { DRDATA (PWRTIME, ptp_ptime, 24), PV_LEFT }, - { FLDATA (STOP_IOE, ptp_stopioe, 0) }, - { NULL } }; + { ORDATA (BUF, ptp_unit.buf, 8) }, + { FLDATA (READY, dev_int, INT_V_PTP) }, + { FLDATA (ENABLE, dev_enb, INT_V_PTP) }, + { FLDATA (POWER, ptp_power, 0) }, + { DRDATA (POS, ptp_unit.pos, T_ADDR_W), PV_LEFT }, + { ORDATA (PSTATE, ptp_unit.STA, 2), REG_HIDDEN }, + { 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, pt_mod, - 1, 10, 31, 1, 8, 8, - NULL, NULL, &ptp_reset, - NULL, &pt_attach, NULL, - &ptp_dib, 0 }; - + "PTP", &ptp_unit, ptp_reg, pt_mod, + 1, 10, 31, 1, 8, 8, + NULL, NULL, &ptp_reset, + NULL, &pt_attach, NULL, + &ptp_dib, 0 + }; + /* TTY data structures - tty_dev TTY device descriptor - tty_unit TTY unit descriptor - tty_reg TTY register list - tty_mod TTy modifiers list + 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 TTR 2 -#define TTP 3 +#define TTI 0 +#define TTO 1 +#define TTR 2 +#define TTP 3 DIB tty_dib = { TTY, IOBUS, 1, &ttyio }; UNIT tty_unit[] = { - { UDATA (&tti_svc, UNIT_KSR, 0), KBD_POLL_WAIT }, - { UDATA (&tto_svc, UNIT_KSR, 0), SERIAL_OUT_WAIT }, - { UDATA (NULL, UNIT_SEQ+UNIT_ATTABLE+UNIT_ROABLE, 0) }, - { UDATA (NULL, UNIT_SEQ+UNIT_ATTABLE, 0) } }; + { UDATA (&tti_svc, UNIT_KSR, 0), KBD_POLL_WAIT }, + { UDATA (&tto_svc, UNIT_KSR, 0), SERIAL_OUT_WAIT }, + { UDATA (NULL, UNIT_SEQ+UNIT_ATTABLE+UNIT_ROABLE, 0) }, + { UDATA (NULL, UNIT_SEQ+UNIT_ATTABLE, 0) } + }; REG tty_reg[] = { - { ORDATA (BUF, tty_buf, 8) }, - { FLDATA (MODE, tty_mode, 0) }, - { FLDATA (READY, dev_int, INT_V_TTY) }, - { FLDATA (ENABLE, dev_enb, 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 }, - { ORDATA (RXOFF, ttr_xoff_read, 2), REG_HIDDEN }, - { ORDATA (RSTATE, tty_unit[TTR].STA, 2), REG_HIDDEN }, - { DRDATA (RPOS, tty_unit[TTR].pos, T_ADDR_W), PV_LEFT }, - { ORDATA (PTAPE, ttp_tape_rcvd, 2), REG_HIDDEN }, - { ORDATA (PXOFF, ttp_xoff_rcvd, 2), REG_HIDDEN }, - { ORDATA (PSTATE, tty_unit[TTP].STA, 2), REG_HIDDEN }, - { DRDATA (PPOS, tty_unit[TTP].pos, T_ADDR_W), PV_LEFT }, - { FLDATA (STOP_IOE, ttr_stopioe, 0) }, - { NULL } }; + { ORDATA (BUF, tty_buf, 8) }, + { FLDATA (MODE, tty_mode, 0) }, + { FLDATA (READY, dev_int, INT_V_TTY) }, + { FLDATA (ENABLE, dev_enb, 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 }, + { ORDATA (RXOFF, ttr_xoff_read, 2), REG_HIDDEN }, + { ORDATA (RSTATE, tty_unit[TTR].STA, 2), REG_HIDDEN }, + { DRDATA (RPOS, tty_unit[TTR].pos, T_ADDR_W), PV_LEFT }, + { ORDATA (PTAPE, ttp_tape_rcvd, 2), REG_HIDDEN }, + { ORDATA (PXOFF, ttp_xoff_rcvd, 2), REG_HIDDEN }, + { ORDATA (PSTATE, tty_unit[TTP].STA, 2), REG_HIDDEN }, + { DRDATA (PPOS, tty_unit[TTP].pos, T_ADDR_W), PV_LEFT }, + { FLDATA (STOP_IOE, ttr_stopioe, 0) }, + { NULL } + }; MTAB tty_mod[] = { - { UNIT_KSR+UNIT_8B+UNIT_ATTABLE, UNIT_KSR, "KSR", "KSR", &ttio_set_mode }, - { UNIT_KSR+UNIT_8B+UNIT_ATTABLE, 0 , "7b" , "7B" , &ttio_set_mode }, - { UNIT_KSR+UNIT_8B+UNIT_ATTABLE, UNIT_8B , "8b" , "8B" , &ttio_set_mode }, - { UNIT_ATTABLE+UNIT_ASC+UNIT_UASC, UNIT_ATTABLE, NULL, "BINARY", - &ttrp_set_mode }, - { UNIT_ATTABLE+UNIT_ASC+UNIT_UASC, UNIT_ATTABLE+UNIT_ASC, "ASCII", "ASCII", - &ttrp_set_mode }, - { UNIT_ATTABLE+UNIT_ASC+UNIT_UASC, UNIT_ATTABLE+UNIT_ASC+UNIT_UASC, "Unix ASCII", "UASCII", - &ttrp_set_mode }, - { MTAB_XTD|MTAB_VUN|MTAB_NMO, 1, NULL, "START", &ttrp_set_start_stop }, - { MTAB_XTD|MTAB_VUN|MTAB_NMO, 0, NULL, "STOP", &ttrp_set_start_stop }, - { 0 } }; + { UNIT_KSR+UNIT_8B+UNIT_ATTABLE, UNIT_KSR, "KSR", "KSR", &ttio_set_mode }, + { UNIT_KSR+UNIT_8B+UNIT_ATTABLE, 0 , "7b" , "7B" , &ttio_set_mode }, + { UNIT_KSR+UNIT_8B+UNIT_ATTABLE, UNIT_8B , "8b" , "8B" , &ttio_set_mode }, + { UNIT_ATTABLE+UNIT_ASC+UNIT_UASC, UNIT_ATTABLE, NULL, "BINARY", + &ttrp_set_mode }, + { UNIT_ATTABLE+UNIT_ASC+UNIT_UASC, UNIT_ATTABLE+UNIT_ASC, "ASCII", "ASCII", + &ttrp_set_mode }, + { UNIT_ATTABLE+UNIT_ASC+UNIT_UASC, UNIT_ATTABLE+UNIT_ASC+UNIT_UASC, "Unix ASCII", "UASCII", + &ttrp_set_mode }, + { MTAB_XTD|MTAB_VUN|MTAB_NMO, 1, NULL, "START", &ttrp_set_start_stop }, + { MTAB_XTD|MTAB_VUN|MTAB_NMO, 0, NULL, "STOP", &ttrp_set_start_stop }, + { 0 } + }; DEVICE tty_dev = { - "TTY", tty_unit, tty_reg, tty_mod, - 4, 10, 31, 1, 8, 8, - NULL, NULL, &tty_reset, - NULL, &pt_attach, &pt_detach, - &tty_dib, 0 }; + "TTY", tty_unit, tty_reg, tty_mod, + 4, 10, 31, 1, 8, 8, + NULL, NULL, &tty_reset, + NULL, &pt_attach, &pt_detach, + &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 + clk_dev CLK device descriptor + clk_unit CLK unit descriptor + clk_mod CLK modifiers + clk_reg CLK register list */ DIB clk_dib = { CLK_KEYS, IOBUS, 1, &clkio }; -UNIT clk_unit = { - UDATA (&clk_svc, 0, 0), 16000 }; +UNIT clk_unit = { UDATA (&clk_svc, 0, 0), 16000 }; REG clk_reg[] = { - { FLDATA (READY, dev_int, INT_V_CLK) }, - { FLDATA (ENABLE, dev_enb, INT_V_CLK) }, - { DRDATA (TIME, clk_unit.wait, 24), REG_NZ + PV_LEFT }, - { DRDATA (TPS, clk_tps, 8), PV_LEFT + REG_HRO }, - { NULL } }; + { FLDATA (READY, dev_int, INT_V_CLK) }, + { FLDATA (ENABLE, dev_enb, 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 } }; + { 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, - &clk_dib, 0 }; - + "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: IO routine */ int32 ptrio (int32 inst, int32 fnc, int32 dat, int32 dev) { -switch (inst) { /* case on opcode */ -case ioOCP: /* OCP */ - if (fnc & 016) return IOBADFNC (dat); /* only fnc 0,1 */ - ptr_motion = fnc ^ 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 == 000) && TST_INT (INT_PTR)) || /* fnc 0? skip rdy */ - ((fnc == 004) && !TST_INTREQ (INT_PTR))) /* fnc 4? skip !int */ - return IOSKIP (dat); - break; -case ioINA: /* INA */ - if (fnc) return IOBADFNC (dat); /* only fnc 0 */ - if (TST_INT (INT_PTR)) { /* ready? */ - CLR_INT (INT_PTR); /* clear ready */ - if (ptr_motion) /* if motion, restart */ - sim_activate (&ptr_unit, ptr_unit.wait); - return IOSKIP (ptr_unit.buf | dat); } /* ret buf, skip */ - break; } /* end case op */ +switch (inst) { /* case on opcode */ + + case ioOCP: /* OCP */ + if (fnc & 016) return IOBADFNC (dat); /* only fnc 0,1 */ + ptr_motion = fnc ^ 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 == 000) && TST_INT (INT_PTR)) || /* fnc 0? skip rdy */ + ((fnc == 004) && !TST_INTREQ (INT_PTR))) /* fnc 4? skip !int */ + return IOSKIP (dat); + break; + + case ioINA: /* INA */ + if (fnc) return IOBADFNC (dat); /* only fnc 0 */ + if (TST_INT (INT_PTR)) { /* ready? */ + CLR_INT (INT_PTR); /* clear ready */ + if (ptr_motion) /* if motion, restart */ + sim_activate (&ptr_unit, ptr_unit.wait); + return IOSKIP (ptr_unit.buf | dat); /* ret buf, skip */ + } + break; + } /* end case op */ + return dat; } @@ -337,28 +356,32 @@ t_stat ptr_svc (UNIT *uptr) { int32 c; -if ((uptr->flags & UNIT_ATT) == 0) /* attached? */ - return IORETURN (ptr_stopioe, SCPE_UNATT); -if (uptr->STA & LF_PEND) { /* lf pending? */ - uptr->STA &= ~LF_PEND; /* clear flag */ - c = 0212; /* insert LF */ - } -else { if ((c = getc (uptr->fileref)) == EOF) { /* read byte */ - if (feof (uptr->fileref)) { - 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; } - if ((uptr->flags & UNIT_UASC) && (c == '\n')) { /* Unix newline? */ - c = 0215; /* insert CR */ - uptr->STA |= LF_PEND; } /* lf pending */ - else if ((uptr->flags & UNIT_ASC) && (c != 0)) /* ASCII? */ - c = c | 0200; - uptr->pos = ftell (uptr->fileref); /* update pos */ - } -SET_INT (INT_PTR); /* set ready flag */ -uptr->buf = c & 0377; /* get byte */ +if ((uptr->flags & UNIT_ATT) == 0) /* attached? */ + return IORETURN (ptr_stopioe, SCPE_UNATT); +if (uptr->STA & LF_PEND) { /* lf pending? */ + uptr->STA &= ~LF_PEND; /* clear flag */ + c = 0212; /* insert LF */ + } +else { + if ((c = getc (uptr->fileref)) == EOF) { /* read byte */ + if (feof (uptr->fileref)) { + 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; + } + if ((uptr->flags & UNIT_UASC) && (c == '\n')) { /* Unix newline? */ + c = 0215; /* insert CR */ + uptr->STA |= LF_PEND; /* lf pending */ + } + else if ((uptr->flags & UNIT_ASC) && (c != 0)) /* ASCII? */ + c = c | 0200; + uptr->pos = ftell (uptr->fileref); /* update pos */ + } +SET_INT (INT_PTR); /* set ready flag */ +uptr->buf = c & 0377; /* get byte */ return SCPE_OK; } @@ -370,12 +393,12 @@ t_stat r; if (!(uptr->flags & UNIT_ATTABLE)) return SCPE_NOFNC; if (r = attach_unit (uptr, cptr)) return r; -if (sim_switches & SWMASK ('A')) /* -a? ASCII */ - uptr->flags |= UNIT_ASC; -else if (sim_switches & SWMASK ('U')) /* -u? Unix ASCII */ - uptr->flags |= (UNIT_ASC|UNIT_UASC); -else if (sim_switches & SWMASK ('B')) /* -b? binary */ - uptr->flags &= ~(UNIT_ASC|UNIT_UASC); +if (sim_switches & SWMASK ('A')) /* -a? ASCII */ + uptr->flags |= UNIT_ASC; +else if (sim_switches & SWMASK ('U')) /* -u? Unix ASCII */ + uptr->flags |= (UNIT_ASC|UNIT_UASC); +else if (sim_switches & SWMASK ('B')) /* -b? binary */ + uptr->flags &= ~(UNIT_ASC|UNIT_UASC); uptr->STA = 0; return r; } @@ -384,7 +407,7 @@ return r; t_stat pt_detach (UNIT *uptr) { -if (!(sim_switches & SIM_SW_REST)) sim_cancel (uptr); /* stop motion */ +if (!(sim_switches & SIM_SW_REST)) sim_cancel (uptr); /* stop motion */ uptr->STA = 0; return detach_unit (uptr); } @@ -393,79 +416,86 @@ return detach_unit (uptr); t_stat ptr_reset (DEVICE *dptr) { -CLR_INT (INT_PTR); /* clear ready, enb */ +CLR_INT (INT_PTR); /* clear ready, enb */ CLR_ENB (INT_PTR); -ptr_unit.buf = 0; /* clear buffer */ +ptr_unit.buf = 0; /* clear buffer */ ptr_unit.STA = 0; -ptr_motion = 0; /* unit stopped */ -sim_cancel (&ptr_unit); /* deactivate unit */ +ptr_motion = 0; /* unit stopped */ +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)) +#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 */ -}; + 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; +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, int32 dev) { -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_INT (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 == 000) && TST_INT (INT_PTP)) || /* fnc 0? skip rdy */ - ((fnc == 001) && /* fnc 1? skip ptp on */ - (ptp_power || sim_is_active (&ptp_unit))) || - ((fnc == 004) && !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_INT (INT_PTP)) { /* if ptp ready */ - CLR_INT (INT_PTP); /* clear ready */ - ptp_unit.buf = dat & 0377; /* store byte */ - sim_activate (&ptp_unit, ptp_unit.wait); - return IOSKIP (dat); } /* skip return */ - break; } +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_INT (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 == 000) && TST_INT (INT_PTP)) || /* fnc 0? skip rdy */ + ((fnc == 001) && /* fnc 1? skip ptp on */ + (ptp_power || sim_is_active (&ptp_unit))) || + ((fnc == 004) && !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_INT (INT_PTP)) { /* if ptp ready */ + CLR_INT (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; } @@ -475,23 +505,26 @@ t_stat ptp_svc (UNIT *uptr) { int32 c; -SET_INT (INT_PTP); /* set flag */ -if (ptp_power == 0) { /* power on? */ - ptp_power = 1; /* ptp is ready */ - return SCPE_OK; } -if ((uptr->flags & UNIT_ATT) == 0) /* attached? */ - return IORETURN (ptp_stopioe, SCPE_UNATT); -if (uptr->flags & UNIT_ASC) { /* ASCII? */ - c = uptr->buf & 0177; /* mask to 7b */ - if ((uptr->flags & UNIT_UASC) && (c == 015)) /* cr? drop if Unix */ - return SCPE_OK; - else if (c == 012) c = '\n'; } /* lf? cvt to nl */ -else c = uptr->buf & 0377; /* no, binary */ -if (putc (c, uptr->fileref) == EOF) { /* output byte */ - perror ("PTP I/O error"); - clearerr (uptr->fileref); - return SCPE_IOERR; } -uptr->pos = ftell (uptr->fileref); /* update pos */ +SET_INT (INT_PTP); /* set flag */ +if (ptp_power == 0) { /* power on? */ + ptp_power = 1; /* ptp is ready */ + return SCPE_OK; + } +if ((uptr->flags & UNIT_ATT) == 0) /* attached? */ + return IORETURN (ptp_stopioe, SCPE_UNATT); +if (uptr->flags & UNIT_ASC) { /* ASCII? */ + c = uptr->buf & 0177; /* mask to 7b */ + if ((uptr->flags & UNIT_UASC) && (c == 015)) /* cr? drop if Unix */ + return SCPE_OK; + else if (c == 012) c = '\n'; /* lf? cvt to nl */ + } +else c = uptr->buf & 0377; /* no, binary */ +if (putc (c, uptr->fileref) == EOF) { /* output byte */ + perror ("PTP I/O error"); + clearerr (uptr->fileref); + return SCPE_IOERR; + } +uptr->pos = ftell (uptr->fileref); /* update pos */ return SCPE_OK; } @@ -499,59 +532,71 @@ return SCPE_OK; t_stat ptp_reset (DEVICE *dptr) { -CLR_INT (INT_PTP); /* clear ready, enb */ +CLR_INT (INT_PTP); /* clear ready, enb */ CLR_ENB (INT_PTP); -ptp_power = 0; /* power off */ -ptp_unit.buf = 0; /* clear buffer */ +ptp_power = 0; /* power off */ +ptp_unit.buf = 0; /* clear buffer */ ptp_unit.STA = 0; -sim_cancel (&ptp_unit); /* deactivate unit */ +sim_cancel (&ptp_unit); /* deactivate unit */ return SCPE_OK; } - + /* Terminal: IO routine */ int32 ttyio (int32 inst, int32 fnc, int32 dat, int32 dev) { -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_INT (INT_TTY); - tty_mode = 1; } /* mode is output */ - else if ((fnc == 0) && tty_mode) { /* output to input? */ - CLR_INT (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 == 000) && TST_INT (INT_TTY)) || /* fnc 0? skip rdy */ - ((fnc == 001) && /* fnc 1? skip !busy */ - (!tty_mode || !sim_is_active (&tty_unit[TTO]))) || - ((fnc == 004) && !TST_INTREQ (INT_TTY)) || /* fnc 4? skip !int */ - ((fnc == 005) && (tty_mode || /* fnc 5? skip !xoff */ - ((tty_buf & 0177) != XOFF)))) /* input & XOFF char */ - return IOSKIP (dat); - break; -case ioINA: /* INA */ - if (fnc & 005) return IOBADFNC (dat); /* only 0,2 */ - if (TST_INT (INT_TTY)) { /* ready? */ - if (tty_mode == 0) CLR_INT (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_INT (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_INT (INT_TTY); } - return IOSKIP (dat); } - break; } /* end case op */ +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_INT (INT_TTY); + tty_mode = 1; /* mode is output */ + } + else if ((fnc == 0) && tty_mode) { /* output to input? */ + CLR_INT (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 == 000) && TST_INT (INT_TTY)) || /* fnc 0? skip rdy */ + ((fnc == 001) && /* fnc 1? skip !busy */ + (!tty_mode || !sim_is_active (&tty_unit[TTO]))) || + ((fnc == 004) && !TST_INTREQ (INT_TTY)) || /* fnc 4? skip !int */ + ((fnc == 005) && (tty_mode || /* fnc 5? skip !xoff */ + ((tty_buf & 0177) != XOFF)))) /* input & XOFF char */ + return IOSKIP (dat); + break; + + case ioINA: /* INA */ + if (fnc & 005) return IOBADFNC (dat); /* only 0,2 */ + if (TST_INT (INT_TTY)) { /* ready? */ + if (tty_mode == 0) CLR_INT (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_INT (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_INT (INT_TTY); + } + return IOSKIP (dat); + } + break; + } /* end case op */ + return dat; } @@ -562,52 +607,59 @@ t_stat tti_svc (UNIT *uptr) int32 out, c; UNIT *ruptr = &tty_unit[TTR]; -sim_activate (uptr, uptr->wait); /* continue poll */ -if ((c = sim_poll_kbd ()) >= SCPE_KFLAG) { /* character? */ - out = c & 0177; /* mask echo to 7b */ - if (c & SCPE_BREAK) c = 0; /* break? */ - else if (uptr->flags & UNIT_KSR) { /* KSR? */ - if (islower (out)) out = toupper (out); /* cvt to UC */ - c = out | 0200; } /* add TTY bit */ - else if (!(uptr->flags & UNIT_8B)) c = out; /* 7b? */ - uptr->pos = uptr->pos + 1; - } -else if (c != SCPE_OK) return c; /* error? */ -else if ((ruptr->flags & UNIT_ATT) && /* TTR attached */ - (ruptr->STA & RUNNING)) { /* and running? */ - if (ruptr->STA & LF_PEND) { /* lf pending? */ - c = 0212; /* char is lf */ - ruptr->STA &= LF_PEND; } /* clear flag */ - else { /* normal read */ - if ((c = getc (ruptr->fileref)) == EOF) { /* read byte */ - if (feof (ruptr->fileref)) { /* EOF? */ - ruptr->STA &= ~RUNNING; /* stop reader */ - if (ttr_stopioe) printf ("TTR end of file\n"); - else return SCPE_OK; } - else perror ("TTR I/O error"); - clearerr (ruptr->fileref); - return SCPE_IOERR; } - if ((ruptr->flags & UNIT_UASC) && (c == '\n')) { - c = 0215; /* Unix ASCII NL? */ - ruptr->STA |= LF_PEND; } /* LF pending */ - else if ((ruptr->flags & UNIT_ASC) && (c != 0)) - c = c | 0200; /* ASCII nz? cvt */ - ruptr->pos = ftell (ruptr->fileref); - } - if (ttr_xoff_read != 0) { /* reader stopping? */ - if (c == RUBOUT) ttr_xoff_read = 0; /* rubout? stop */ - else ttr_xoff_read--; /* else decr state */ - if (ttr_xoff_read == 0) /* delay done? */ - ruptr->STA &= ~RUNNING; } /* stop reader */ - else if ((c & 0177) == XOFF) ttr_xoff_read = 2; /* XOFF read? */ - out = c; /* echo char */ - } -else return SCPE_OK; /* no char */ -if (tty_mode == 0) { /* input mode? */ - tty_buf = c & 0377; /* put char in buf */ - SET_INT (INT_TTY); } /* set flag */ -tto_write (out); /* echo to printer */ -return ttp_write (out); /* and punch */ +sim_activate (uptr, uptr->wait); /* continue poll */ +if ((c = sim_poll_kbd ()) >= SCPE_KFLAG) { /* character? */ + out = c & 0177; /* mask echo to 7b */ + if (c & SCPE_BREAK) c = 0; /* break? */ + else if (uptr->flags & UNIT_KSR) { /* KSR? */ + if (islower (out)) out = toupper (out); /* cvt to UC */ + c = out | 0200; /* add TTY bit */ + } + else if (!(uptr->flags & UNIT_8B)) c = out; /* 7b? */ + uptr->pos = uptr->pos + 1; + } +else if (c != SCPE_OK) return c; /* error? */ +else if ((ruptr->flags & UNIT_ATT) && /* TTR attached */ + (ruptr->STA & RUNNING)) { /* and running? */ + if (ruptr->STA & LF_PEND) { /* lf pending? */ + c = 0212; /* char is lf */ + ruptr->STA &= LF_PEND; /* clear flag */ + } + else { /* normal read */ + if ((c = getc (ruptr->fileref)) == EOF) { /* read byte */ + if (feof (ruptr->fileref)) { /* EOF? */ + ruptr->STA &= ~RUNNING; /* stop reader */ + if (ttr_stopioe) printf ("TTR end of file\n"); + else return SCPE_OK; + } + else perror ("TTR I/O error"); + clearerr (ruptr->fileref); + return SCPE_IOERR; + } + if ((ruptr->flags & UNIT_UASC) && (c == '\n')) { + c = 0215; /* Unix ASCII NL? */ + ruptr->STA |= LF_PEND; /* LF pending */ + } + else if ((ruptr->flags & UNIT_ASC) && (c != 0)) + c = c | 0200; /* ASCII nz? cvt */ + ruptr->pos = ftell (ruptr->fileref); + } + if (ttr_xoff_read != 0) { /* reader stopping? */ + if (c == RUBOUT) ttr_xoff_read = 0; /* rubout? stop */ + else ttr_xoff_read--; /* else decr state */ + if (ttr_xoff_read == 0) /* delay done? */ + ruptr->STA &= ~RUNNING; /* stop reader */ + } + else if ((c & 0177) == XOFF) ttr_xoff_read = 2; /* XOFF read? */ + out = c; /* echo char */ + } +else return SCPE_OK; /* no char */ +if (tty_mode == 0) { /* input mode? */ + tty_buf = c & 0377; /* put char in buf */ + SET_INT (INT_TTY); /* set flag */ + } +tto_write (out); /* echo to printer */ +return ttp_write (out); /* and punch */ } /* Output service - printer and punch */ @@ -620,23 +672,27 @@ UNIT *puptr = &tty_unit[TTP]; t_stat r; c7b = tty_buf & 0177; -if (ttp_tape_rcvd != 0) { /* prev = tape? */ - ttp_tape_rcvd--; /* decrement state */ - if ((ttp_tape_rcvd == 0) && (puptr->flags & UNIT_ATT)) - puptr->STA |= RUNNING; } /* start after delay */ -else if (c7b == TAPE) ttp_tape_rcvd = 2; /* char = TAPE? */ -if (ttp_xoff_rcvd != 0) { /* prev = XOFF? */ - ttp_xoff_rcvd--; /* decrement state */ - if (ttp_xoff_rcvd == 0) puptr->STA &= RUNNING; } /* stop after delay */ -else if (c7b == XOFF) ttp_xoff_rcvd = 2; /* char = XOFF? */ -if ((c7b == XON) && (ruptr->flags & UNIT_ATT)) { /* char = XON? */ - ruptr->STA |= RUNNING; /* start reader */ - ttr_xoff_read = 0; } /* cancel stop */ -if ((r = tto_write (tty_buf)) != SCPE_OK) { /* print; error? */ - sim_activate (uptr, uptr->wait); /* try again */ - return ((r == SCPE_STALL)? SCPE_OK: r); } /* !stall? report */ -if ((r = ttp_write (tty_buf)) != SCPE_OK) return r; /* punch; error? */ -SET_INT (INT_TTY); /* set done flag */ +if (ttp_tape_rcvd != 0) { /* prev = tape? */ + ttp_tape_rcvd--; /* decrement state */ + if ((ttp_tape_rcvd == 0) && (puptr->flags & UNIT_ATT)) + puptr->STA |= RUNNING; /* start after delay */ + } +else if (c7b == TAPE) ttp_tape_rcvd = 2; /* char = TAPE? */ +if (ttp_xoff_rcvd != 0) { /* prev = XOFF? */ + ttp_xoff_rcvd--; /* decrement state */ + if (ttp_xoff_rcvd == 0) puptr->STA &= RUNNING; /* stop after delay */ + } +else if (c7b == XOFF) ttp_xoff_rcvd = 2; /* char = XOFF? */ +if ((c7b == XON) && (ruptr->flags & UNIT_ATT)) { /* char = XON? */ + ruptr->STA |= RUNNING; /* start reader */ + ttr_xoff_read = 0; /* cancel stop */ + } +if ((r = tto_write (tty_buf)) != SCPE_OK) { /* print; error? */ + sim_activate (uptr, uptr->wait); /* try again */ + return ((r == SCPE_STALL)? SCPE_OK: r); /* !stall? report */ + } +if ((r = ttp_write (tty_buf)) != SCPE_OK) return r; /* punch; error? */ +SET_INT (INT_TTY); /* set done flag */ return SCPE_OK; } @@ -646,15 +702,16 @@ t_stat tto_write (int32 c) { UNIT *tuptr = &tty_unit[TTO]; -if (tuptr->flags & UNIT_8B) c = c & 0377; /* 8b? */ -else { c = c & 0177; /* 7b, KSR: mask */ - if (c) return SCPE_OK; /* supress NUL */ - if (tuptr->flags & UNIT_KSR) { /* KSR? */ - if ((c < 040) && /* not in ctrl set? */ - !(CNTL_SET & CHAR_FLAG (c))) return SCPE_OK; - if (islower (c)) c = toupper (c); /* cvt to UC */ - } - } +if (tuptr->flags & UNIT_8B) c = c & 0377; /* 8b? */ +else { + c = c & 0177; /* 7b, KSR: mask */ + if (c) return SCPE_OK; /* supress NUL */ + if (tuptr->flags & UNIT_KSR) { /* KSR? */ + if ((c < 040) && /* not in ctrl set? */ + !(CNTL_SET & CHAR_FLAG (c))) return SCPE_OK; + if (islower (c)) c = toupper (c); /* cvt to UC */ + } + } tuptr->pos = tuptr->pos + 1; return sim_putchar_s (c); } @@ -666,21 +723,23 @@ t_stat ttp_write (int32 c) uint32 p, c7b; UNIT *puptr = &tty_unit[TTP]; -if ((puptr->flags & UNIT_ATT) && /* TTP attached */ - (puptr->STA & RUNNING)) { /* and running? */ - c7b = c & 0177; - if (!(puptr->flags & UNIT_UASC) || (c7b != 015)) { - if (puptr->flags & UNIT_ASC) { /* ASCII? */ - if (c7b == 012) p = '\n'; /* cvt LF */ - else p = c7b; } /* else 7b */ - else p = c; /* untouched */ - if (putc (p, puptr->fileref) == EOF) { /* output byte */ - perror ("TTP I/O error"); - clearerr (puptr->fileref); - return SCPE_IOERR; } - puptr->pos = ftell (puptr->fileref); /* update pos */ - } - } +if ((puptr->flags & UNIT_ATT) && /* TTP attached */ + (puptr->STA & RUNNING)) { /* and running? */ + c7b = c & 0177; + if (!(puptr->flags & UNIT_UASC) || (c7b != 015)) { + if (puptr->flags & UNIT_ASC) { /* ASCII? */ + if (c7b == 012) p = '\n'; /* cvt LF */ + else p = c7b; /* else 7b */ + } + else p = c; /* untouched */ + if (putc (p, puptr->fileref) == EOF) { /* output byte */ + perror ("TTP I/O error"); + clearerr (puptr->fileref); + return SCPE_IOERR; + } + puptr->pos = ftell (puptr->fileref); /* update pos */ + } + } return SCPE_OK; } @@ -688,17 +747,17 @@ return SCPE_OK; t_stat tty_reset (DEVICE *dptr) { -CLR_INT (INT_TTY); /* clear ready, enb */ +CLR_INT (INT_TTY); /* clear ready, enb */ CLR_ENB (INT_TTY); -tty_mode = 0; /* mode = input */ +tty_mode = 0; /* mode = input */ tty_buf = 0; -ttr_xoff_read = 0; /* clr TTR, TTP flags */ +ttr_xoff_read = 0; /* clr TTR, TTP flags */ ttp_tape_rcvd = 0; ttp_xoff_rcvd = 0; tty_unit[TTR].STA = 0; tty_unit[TTP].STA = 0; -sim_activate (&tty_unit[TTI], tty_unit[TTI].wait); /* activate poll */ -sim_cancel (&tty_unit[TTO]); /* cancel output */ +sim_activate (&tty_unit[TTI], tty_unit[TTI].wait); /* activate poll */ +sim_cancel (&tty_unit[TTO]); /* cancel output */ return SCPE_OK; } @@ -706,7 +765,7 @@ return SCPE_OK; t_stat ttio_set_mode (UNIT *uptr, int32 val, char *cptr, void *desc) { -if (uptr->flags & UNIT_ATTABLE) return SCPE_NOFNC; /* not TTR, TTP */ +if (uptr->flags & UNIT_ATTABLE) return SCPE_NOFNC; /* not TTR, TTP */ 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; @@ -716,7 +775,7 @@ return SCPE_OK; t_stat ttrp_set_mode (UNIT *uptr, int32 val, char *cptr, void *desc) { -if (!(uptr->flags & UNIT_ATTABLE)) return SCPE_NOFNC; /* TTR, TTP only */ +if (!(uptr->flags & UNIT_ATTABLE)) return SCPE_NOFNC; /* TTR, TTP only */ if (!(val & UNIT_UASC)) uptr->STA &= ~LF_PEND; return SCPE_OK; } @@ -725,52 +784,63 @@ return SCPE_OK; t_stat ttrp_set_start_stop (UNIT *uptr, int32 val, char *cptr, void *desc) { -if (!(uptr->flags & UNIT_ATTABLE)) return SCPE_NOFNC; /* TTR, TTP only */ -if (!(uptr->flags & UNIT_ATT)) return SCPE_UNATT; /* must be attached */ -if (val) uptr->STA |= RUNNING; /* start? set running */ -else uptr->STA &= ~RUNNING; /* stop? clr running */ -if (uptr->flags & UNIT_ROABLE) ttr_xoff_read = 0; /* TTR? cancel stop */ -else ttp_tape_rcvd = ttp_xoff_rcvd = 0; /* TTP? cancel all */ +if (!(uptr->flags & UNIT_ATTABLE)) return SCPE_NOFNC; /* TTR, TTP only */ +if (!(uptr->flags & UNIT_ATT)) return SCPE_UNATT; /* must be attached */ +if (val) uptr->STA |= RUNNING; /* start? set running */ +else uptr->STA &= ~RUNNING; /* stop? clr running */ +if (uptr->flags & UNIT_ROABLE) ttr_xoff_read = 0; /* TTR? cancel stop */ +else ttp_tape_rcvd = ttp_xoff_rcvd = 0; /* TTP? cancel all */ return SCPE_OK; } - + /* Clock/options: IO routine */ int32 clkio (int32 inst, int32 fnc, int32 dat, int32 dev) { -switch (inst) { /* case on opcode */ -case ioOCP: /* OCP */ - if (fnc & 015) return IOBADFNC (dat); /* only fnc 0,2 */ - CLR_INT (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 == 000) { /* clock skip !int */ - if (!TST_INTREQ (INT_CLK)) return IOSKIP (dat); } - else if ((fnc & 007) == 002) { /* mem parity? */ - if (((fnc == 002) && !TST_INT (INT_MPE)) || - ((fnc == 012) && TST_INT (INT_MPE))) - return IOSKIP (dat); } - else return IOBADFNC (dat); /* invalid fnc */ - break; -case ioOTA: /* OTA */ - if (fnc == 000) dev_enb = 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; } +switch (inst) { /* case on opcode */ + + case ioOCP: /* OCP */ + if (fnc & 015) return IOBADFNC (dat); /* only fnc 0,2 */ + CLR_INT (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 == 000) { /* clock skip !int */ + if (!TST_INTREQ (INT_CLK)) return IOSKIP (dat); + } + else if ((fnc & 007) == 002) { /* mem parity? */ + if (((fnc == 002) && !TST_INT (INT_MPE)) || + ((fnc == 012) && TST_INT (INT_MPE))) + return IOSKIP (dat); + } + else return IOBADFNC (dat); /* invalid fnc */ + break; + + case ioOTA: /* OTA */ + if (fnc == 000) dev_enb = 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; } @@ -779,9 +849,9 @@ return dat; t_stat clk_svc (UNIT *uptr) { -M[M_CLK] = M[M_CLK + 1] & DMASK; /* increment mem ctr */ -if (M[M_CLK] == 0) SET_INT (INT_CLK); /* = 0? set flag */ -sim_activate (&clk_unit, sim_rtc_calb (clk_tps)); /* reactivate */ +M[M_CLK] = M[M_CLK + 1] & DMASK; /* increment mem ctr */ +if (M[M_CLK] == 0) SET_INT (INT_CLK); /* = 0? set flag */ +sim_activate (&clk_unit, sim_rtc_calb (clk_tps)); /* reactivate */ return SCPE_OK; } @@ -789,9 +859,9 @@ return SCPE_OK; t_stat clk_reset (DEVICE *dptr) { -CLR_INT (INT_CLK); /* clear ready, enb */ +CLR_INT (INT_CLK); /* clear ready, enb */ CLR_ENB (INT_CLK); -sim_cancel (&clk_unit); /* deactivate unit */ +sim_cancel (&clk_unit); /* deactivate unit */ return SCPE_OK; } diff --git a/H316/h316_sys.c b/H316/h316_sys.c index 96f5dcc6..9995a0b7 100644 --- a/H316/h316_sys.c +++ b/H316/h316_sys.c @@ -1,6 +1,6 @@ /* h316_sys.c: Honeywell 316/516 simulator interface - Copyright (c) 1999-2004, Robert M Supnik + Copyright (c) 1999-2005, 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"), @@ -19,13 +19,13 @@ 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 + 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-Dec-04 RMS Fixed fprint_opr calling sequence - 24-Oct-03 RMS Added DMA/DMC support - 17-Sep-01 RMS Removed multiconsole support + 01-Dec-04 RMS Fixed fprint_opr calling sequence + 24-Oct-03 RMS Added DMA/DMC support + 17-Sep-01 RMS Removed multiconsole support */ #include "h316_defs.h" @@ -47,12 +47,12 @@ 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 + 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"; @@ -62,29 +62,31 @@ 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, - &dp_dev, - &fhd_dev, - &mt_dev, - NULL }; + &cpu_dev, + &ptr_dev, + &ptp_dev, + &tty_dev, + &lpt_dev, + &clk_dev, + &dp_dev, + &fhd_dev, + &mt_dev, + NULL + }; const char *sim_stop_messages[] = { - "Unknown error", - "Unimplemented instruction", - "Unimplemented I/O device", - "HALT instruction", - "Breakpoint", - "Indirect address loop", - "DMA error", - "MT write protected", - "DP write overrun, track destroyed", - "DP track format invalid" }; - + "Unknown error", + "Unimplemented instruction", + "Unimplemented I/O device", + "HALT instruction", + "Breakpoint", + "Indirect address loop", + "DMA error", + "MT write protected", + "DP write overrun, track destroyed", + "DP track format invalid" + }; + /* Binary loader Tbs. @@ -94,29 +96,30 @@ 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) +#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 }; + 0177700, 0177000, 0177000 + }; static const char *opcode[] = { "HLT", "SGL", "DBL", @@ -143,14 +146,15 @@ static const char *opcode[] = { "LGL", "ALS", "ALR", "OCP", "SKS", "INA", "OTA", "SMK", - "SPL", "SPN", "SLZ", /* encode only */ + "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 }; + NULL, NULL, /* decode only */ + NULL + }; static const int32 opc_val[] = { 0000000+I_NPN, 0000005+I_NPN, 0000007+I_NPN, @@ -177,115 +181,129 @@ static const int32 opc_val[] = { 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 */ + 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 }; - + 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? + *of = output stream + inst = mask bits + class = instruction class code + sp = space needed? Outputs: - status = space needed + status = space needed */ void fprint_opr (FILE *of, int32 inst, int32 class) { int32 i, j, sp; -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 == class) && (opc_val[i] & inst)) { /* same class? */ - inst = inst & ~opc_val[i]; /* mask bit set? */ - fprintf (of, (sp? " %s": "%s"), opcode[i]); - sp = 1; } } +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 == 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; } /* Symbolic decode Inputs: - *of = output stream - addr = current PC - *val = pointer to data - *uptr = pointer to unit - sw = switches + *of = output stream + addr = current PC + *val = pointer to data + *uptr = pointer to unit + sw = switches Outputs: - return = status code + 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) + 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 ('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? */ +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); /* print skips */ - break; } /* end case */ - return SCPE_OK; } /* end if */ - } /* end for */ + 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); /* 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 + *cptr = pointer to input string + addr = current PC + *uptr = pointer to unit + *val = pointer to output values + sw = switches Outputs: - status = error status + status = error status */ t_stat parse_sym (char *cptr, t_addr addr, UNIT *uptr, t_value *val, int32 sw) @@ -295,69 +313,81 @@ t_stat r; char gbuf[CBUFSIZE]; cflag = (uptr == NULL) || (uptr == &cpu_unit); -while (isspace (*cptr)) cptr++; /* absorb spaces */ +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 (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; } - + 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 */ +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 */ +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? */ +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 index 43304ed9..3b771c26 100644 --- a/HP2100/hp2100_cpu.c +++ b/HP2100/hp2100_cpu.c @@ -19,81 +19,81 @@ 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 + 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 2116A/2100A/21MX-M/21MX-E central processing unit - MP 12892B memory protect - DMA0,DMA1 12895A/12897B direct memory access/dual channel port controller + CPU 2116A/2100A/21MX-M/21MX-E central processing unit + MP 12892B memory protect + DMA0,DMA1 12895A/12897B direct memory access/dual channel port controller - 21-Jan-05 JDB Reorganized CPU option flags - 15-Jan-05 RMS Split out EAU and MAC instructions - 26-Dec-04 RMS DMA reset doesn't clear alternate CTL flop (from Dave Bryan) - DMA reset shouldn't clear control words (from Dave Bryan) - Alternate CTL flop not visible as register (from Dave Bryan) - Fixed CBS, SBS, TBS to perform virtual reads - Separated A/B from M[0/1] for DMA IO (from Dave Bryan) - Fixed bug in JPY (from Dave Bryan) - 25-Dec-04 JDB Added SET CPU 21MX-M, 21MX-E (21MX defaults to MX-E) - TIMER/EXECUTE/DIAG instructions disabled for 21MX-M - T-register reflects changes in M-register when halted - 25-Sep-04 JDB Moved MP into its own device; added MP option jumpers - Modified DMA to allow disabling - Modified SET CPU 2100/2116 to truncate memory > 32K - Added -F switch to SET CPU to force memory truncation - Fixed S-register behavior on 2116 - Fixed LIx/MIx behavior for DMA on 2116 and 2100 - Fixed LIx/MIx behavior for empty I/O card slots - Modified WRU to be REG_HRO - Added BRK and DEL to save console settings - Fixed use of "unsigned int16" in cpu_reset - Modified memory size routine to return SCPE_INCOMP if - memory size truncation declined - 20-Jul-04 RMS Fixed bug in breakpoint test (reported by Dave Bryan) - Back up PC on instruction errors (from Dave Bryan) - 14-May-04 RMS Fixed bugs and added features from Dave Bryan - - SBT increments B after store - - DMS console map must check dms_enb - - SFS x,C and SFC x,C work - - MP violation clears automatically on interrupt - - SFS/SFC 5 is not gated by protection enabled - - DMS enable does not disable mem prot checks - - DMS status inconsistent at simulator halt - - Examine/deposit are checking wrong addresses - - Physical addresses are 20b not 15b - - Revised DMS to use memory rather than internal format - - Added instruction printout to HALT message - - Added M and T internal registers - - Added N, S, and U breakpoints - Revised IBL facility to conform to microcode - Added DMA EDT I/O pseudo-opcode - Separated DMA SRQ (service request) from FLG - 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 + 21-Jan-05 JDB Reorganized CPU option flags + 15-Jan-05 RMS Split out EAU and MAC instructions + 26-Dec-04 RMS DMA reset doesn't clear alternate CTL flop (from Dave Bryan) + DMA reset shouldn't clear control words (from Dave Bryan) + Alternate CTL flop not visible as register (from Dave Bryan) + Fixed CBS, SBS, TBS to perform virtual reads + Separated A/B from M[0/1] for DMA IO (from Dave Bryan) + Fixed bug in JPY (from Dave Bryan) + 25-Dec-04 JDB Added SET CPU 21MX-M, 21MX-E (21MX defaults to MX-E) + TIMER/EXECUTE/DIAG instructions disabled for 21MX-M + T-register reflects changes in M-register when halted + 25-Sep-04 JDB Moved MP into its own device; added MP option jumpers + Modified DMA to allow disabling + Modified SET CPU 2100/2116 to truncate memory > 32K + Added -F switch to SET CPU to force memory truncation + Fixed S-register behavior on 2116 + Fixed LIx/MIx behavior for DMA on 2116 and 2100 + Fixed LIx/MIx behavior for empty I/O card slots + Modified WRU to be REG_HRO + Added BRK and DEL to save console settings + Fixed use of "unsigned int16" in cpu_reset + Modified memory size routine to return SCPE_INCOMP if + memory size truncation declined + 20-Jul-04 RMS Fixed bug in breakpoint test (reported by Dave Bryan) + Back up PC on instruction errors (from Dave Bryan) + 14-May-04 RMS Fixed bugs and added features from Dave Bryan + - SBT increments B after store + - DMS console map must check dms_enb + - SFS x,C and SFC x,C work + - MP violation clears automatically on interrupt + - SFS/SFC 5 is not gated by protection enabled + - DMS enable does not disable mem prot checks + - DMS status inconsistent at simulator halt + - Examine/deposit are checking wrong addresses + - Physical addresses are 20b not 15b + - Revised DMS to use memory rather than internal format + - Added instruction printout to HALT message + - Added M and T internal registers + - Added N, S, and U breakpoints + Revised IBL facility to conform to microcode + Added DMA EDT I/O pseudo-opcode + Separated DMA SRQ (service request) from FLG + 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 References: - 21MX M-Series Computer, HP 2108B and HP 2112B, Operating and Reference Manual @@ -103,26 +103,26 @@ 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 - MR<14:0> M register - memory address - TR<15:0> T register - memory data - E extend flag (carry out) - O overflow flag + 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 + MR<14:0> M register - memory address + TR<15:0> T register - memory data + 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) + 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 + 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 @@ -136,37 +136,36 @@ |in| op |cp| offset | memory reference +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - <14:11> mnemonic action + <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 + 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 + <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>] + 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: + + The shift format is: 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ @@ -215,9 +214,8 @@ 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 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. @@ -268,9 +266,8 @@ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ |in| operand address | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ -*/ - -/* This routine is the instruction decode routine for the HP 2100. + + 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. @@ -279,20 +276,20 @@ 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 + 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 five 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] - device service requests as bit array dev_srq[3][31..0] + 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] + device service requests as bit array dev_srq[3][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, @@ -316,8 +313,8 @@ 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 + 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 @@ -329,96 +326,98 @@ is no testing for new interrupts during execution (that is, the event timer is not called). */ - + #include "hp2100_defs.h" #include #include "hp2100_cpu.h" -#define UNIT_V_MP_JSB (UNIT_V_UF + 0) /* MP jumper W5 out */ -#define UNIT_V_MP_INT (UNIT_V_UF + 1) /* MP jumper W6 out */ -#define UNIT_V_MP_SEL1 (UNIT_V_UF + 2) /* MP jumper W7 out */ -#define UNIT_MP_JSB (1 << UNIT_V_MP_JSB) -#define UNIT_MP_INT (1 << UNIT_V_MP_INT) -#define UNIT_MP_SEL1 (1 << UNIT_V_MP_SEL1) +#define UNIT_V_MP_JSB (UNIT_V_UF + 0) /* MP jumper W5 out */ +#define UNIT_V_MP_INT (UNIT_V_UF + 1) /* MP jumper W6 out */ +#define UNIT_V_MP_SEL1 (UNIT_V_UF + 2) /* MP jumper W7 out */ +#define UNIT_MP_JSB (1 << UNIT_V_MP_JSB) +#define UNIT_MP_INT (1 << UNIT_V_MP_INT) +#define UNIT_MP_SEL1 (1 << UNIT_V_MP_SEL1) -#define MOD_211X (1 << TYPE_211X) -#define MOD_2100 (1 << TYPE_2100) -#define MOD_21MX (1 << TYPE_21MX) -#define MOD_CURRENT (1 << CPU_TYPE) +#define MOD_211X (1 << TYPE_211X) +#define MOD_2100 (1 << TYPE_2100) +#define MOD_21MX (1 << TYPE_21MX) +#define MOD_CURRENT (1 << CPU_TYPE) -#define UNIT_SYSTEM (UNIT_CPU_MASK | UNIT_OPTS) -#define UNIT_SYS_2116 (UNIT_2116) -#define UNIT_SYS_2100 (UNIT_2100 | UNIT_EAU) -#define UNIT_SYS_21MX_M (UNIT_21MX_M | UNIT_EAU | UNIT_FP | UNIT_DMS) -#define UNIT_SYS_21MX_E (UNIT_21MX_E | UNIT_EAU | UNIT_FP | UNIT_DMS) +#define UNIT_SYSTEM (UNIT_CPU_MASK | UNIT_OPTS) +#define UNIT_SYS_2116 (UNIT_2116) +#define UNIT_SYS_2100 (UNIT_2100 | UNIT_EAU) +#define UNIT_SYS_21MX_M (UNIT_21MX_M | UNIT_EAU | UNIT_FP | UNIT_DMS) +#define UNIT_SYS_21MX_E (UNIT_21MX_E | UNIT_EAU | UNIT_FP | UNIT_DMS) -#define ABORT(val) longjmp (save_env, (val)) +#define ABORT(val) longjmp (save_env, (val)) -#define DMAR0 1 -#define DMAR1 2 +#define DMAR0 1 +#define DMAR1 2 -#define ALL_BKPTS (SWMASK('E')|SWMASK('N')|SWMASK('S')|SWMASK('U')) +#define ALL_BKPTS (SWMASK('E')|SWMASK('N')|SWMASK('S')|SWMASK('U')) -uint16 *M = NULL; /* memory */ -uint32 saved_AR = 0; /* A register */ -uint32 saved_BR = 0; /* B register */ -uint16 ABREG[2]; /* during execution */ -uint32 PC = 0; /* P register */ -uint32 SR = 0; /* S register */ -uint32 MR = 0; /* M register */ -uint32 TR = 0; /* T 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 */ -uint32 dev_srq[2] = { 0 }; /* device svc reqs */ -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 */ -uint16 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 */ +uint16 *M = NULL; /* memory */ +uint32 saved_AR = 0; /* A register */ +uint32 saved_BR = 0; /* B register */ +uint16 ABREG[2]; /* during execution */ +uint32 PC = 0; /* P register */ +uint32 SR = 0; /* S register */ +uint32 MR = 0; /* M register */ +uint32 TR = 0; /* T 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 */ +uint32 dev_srq[2] = { 0 }; /* device svc reqs */ +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 */ +uint16 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; }; +struct opt_table { /* options table */ + int32 optf; + int32 cpuf; + }; static struct opt_table opt_val[] = { - { UNIT_EAU, MOD_211X }, - { UNIT_FP, MOD_2100 }, - { UNIT_DMS, MOD_21MX }, - { UNIT_IOP, MOD_2100 | MOD_21MX }, - { UNIT_FFP, MOD_2100 | MOD_21MX }, - { TYPE_211X, MOD_211X | MOD_2100 | MOD_21MX }, - { TYPE_2100, MOD_211X | MOD_2100 | MOD_21MX }, - { TYPE_21MX, MOD_211X | MOD_2100 | MOD_21MX }, - { 0, 0 } }; + { UNIT_EAU, MOD_211X }, + { UNIT_FP, MOD_2100 }, + { UNIT_DMS, MOD_21MX }, + { UNIT_IOP, MOD_2100 | MOD_21MX }, + { UNIT_FFP, MOD_2100 | MOD_21MX }, + { TYPE_211X, MOD_211X | MOD_2100 | MOD_21MX }, + { TYPE_2100, MOD_211X | MOD_2100 | MOD_21MX }, + { TYPE_21MX, MOD_211X | MOD_2100 | MOD_21MX }, + { 0, 0 } + }; extern int32 sim_interval; extern int32 sim_int_char; extern int32 sim_brk_char; extern int32 sim_del_char; -extern int32 sim_brk_types, sim_brk_dflt, sim_brk_summ; /* breakpoint info */ +extern int32 sim_brk_types, sim_brk_dflt, sim_brk_summ; /* breakpoint info */ extern FILE *sim_log; extern DEVICE *sim_devices[]; extern int32 sim_switches; @@ -453,193 +452,201 @@ extern t_stat cpu_uig_0 (uint32 IR, uint32 intrq); extern t_stat cpu_uig_1 (uint32 IR, uint32 intrq); extern int32 clk_delay (int32 flg); extern void (*sim_vm_post) (t_bool from_scp); - + /* CPU data structures - cpu_dev CPU device descriptor - cpu_unit CPU unit descriptor - cpu_reg CPU register list - cpu_mod CPU modifiers list + 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 (M, MR, 15) }, - { ORDATA (T, TR, 16), REG_RO }, - { ORDATA (X, XR, 16) }, - { ORDATA (Y, YR, 16) }, - { ORDATA (S, SR, 16) }, - { FLDATA (E, E, 0) }, - { FLDATA (O, O, 0) }, - { FLDATA (ION, ion, 0) }, - { FLDATA (ION_DEFER, ion_defer, 0) }, - { ORDATA (CIR, intaddr, 6) }, - { 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, 16, 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), REG_HRO }, - { ORDATA (BRK, sim_brk_char, 8), REG_HRO }, - { ORDATA (DEL, sim_del_char, 8), REG_HRO }, - { 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 }, - { ORDATA (HSRQ, dev_srq[0], 32), REG_HRO }, - { ORDATA (LSRQ, dev_srq[1], 32), REG_HRO }, - { NULL } }; + { ORDATA (P, PC, 15) }, + { ORDATA (A, saved_AR, 16) }, + { ORDATA (B, saved_BR, 16) }, + { ORDATA (M, MR, 15) }, + { ORDATA (T, TR, 16), REG_RO }, + { ORDATA (X, XR, 16) }, + { ORDATA (Y, YR, 16) }, + { ORDATA (S, SR, 16) }, + { FLDATA (E, E, 0) }, + { FLDATA (O, O, 0) }, + { FLDATA (ION, ion, 0) }, + { FLDATA (ION_DEFER, ion_defer, 0) }, + { ORDATA (CIR, intaddr, 6) }, + { 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, 16, 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), REG_HRO }, + { ORDATA (BRK, sim_brk_char, 8), REG_HRO }, + { ORDATA (DEL, sim_del_char, 8), REG_HRO }, + { 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 }, + { ORDATA (HSRQ, dev_srq[0], 32), REG_HRO }, + { ORDATA (LSRQ, dev_srq[1], 32), REG_HRO }, + { NULL } + }; MTAB cpu_mod[] = { - { UNIT_SYSTEM, UNIT_SYS_2116, NULL, "2116", &cpu_set_opt, NULL, - (void *) TYPE_211X }, - { UNIT_SYSTEM, UNIT_SYS_2100, NULL, "2100", &cpu_set_opt, NULL, - (void *) TYPE_2100 }, - { UNIT_SYSTEM, UNIT_SYS_21MX_E, NULL, "21MX-E", &cpu_set_opt, NULL, - (void *) TYPE_21MX }, - { UNIT_SYSTEM, UNIT_SYS_21MX_M, NULL, "21MX-M", &cpu_set_opt, NULL, - (void *) TYPE_21MX }, + { UNIT_SYSTEM, UNIT_SYS_2116, NULL, "2116", &cpu_set_opt, NULL, + (void *) TYPE_211X }, + { UNIT_SYSTEM, UNIT_SYS_2100, NULL, "2100", &cpu_set_opt, NULL, + (void *) TYPE_2100 }, + { UNIT_SYSTEM, UNIT_SYS_21MX_E, NULL, "21MX-E", &cpu_set_opt, NULL, + (void *) TYPE_21MX }, + { UNIT_SYSTEM, UNIT_SYS_21MX_M, NULL, "21MX-M", &cpu_set_opt, NULL, + (void *) TYPE_21MX }, - { UNIT_CPU_MASK, UNIT_2116, "2116", NULL, NULL }, - { UNIT_CPU_MASK, UNIT_2100, "2100", NULL, NULL }, - { UNIT_CPU_MASK, UNIT_21MX_E, "21MX-E", NULL, NULL }, - { UNIT_CPU_MASK, UNIT_21MX_M, "21MX-M", NULL, NULL }, + { UNIT_CPU_MASK, UNIT_2116, "2116", NULL, NULL }, + { UNIT_CPU_MASK, UNIT_2100, "2100", NULL, NULL }, + { UNIT_CPU_MASK, UNIT_21MX_E, "21MX-E", NULL, NULL }, + { UNIT_CPU_MASK, UNIT_21MX_M, "21MX-M", 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_IOP, UNIT_IOP, "IOP", "IOP", &cpu_set_opt, NULL, - (void *) UNIT_IOP }, - { UNIT_IOP, 0, "no IOP", "NOIOP", &cpu_set_opt, NULL, - (void *) UNIT_IOP }, - { 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_FFP, UNIT_FFP, "FFP", "FFP", &cpu_set_opt, NULL, - (void *) UNIT_FFP }, - { UNIT_FFP, 0, "no FFP", "NOFFP", &cpu_set_opt, NULL, - (void *) UNIT_FFP }, - - { MTAB_XTD | MTAB_VDV, 4096, NULL, "4K", &cpu_set_size }, - { MTAB_XTD | MTAB_VDV, 8192, NULL, "8K", &cpu_set_size }, - { MTAB_XTD | MTAB_VDV, 16384, NULL, "16K", &cpu_set_size }, - { MTAB_XTD | MTAB_VDV, 32768, NULL, "32K", &cpu_set_size }, - { MTAB_XTD | MTAB_VDV, 65536, NULL, "64K", &cpu_set_size }, - { MTAB_XTD | MTAB_VDV, 131072, NULL, "128K", &cpu_set_size }, - { MTAB_XTD | MTAB_VDV, 262144, NULL, "256K", &cpu_set_size }, - { MTAB_XTD | MTAB_VDV, 524288, NULL, "512K", &cpu_set_size }, - { MTAB_XTD | MTAB_VDV, 1048576, NULL, "1024K", &cpu_set_size }, - { 0 } }; + { 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_IOP, UNIT_IOP, "IOP", "IOP", &cpu_set_opt, NULL, + (void *) UNIT_IOP }, + { UNIT_IOP, 0, "no IOP", "NOIOP", &cpu_set_opt, NULL, + (void *) UNIT_IOP }, + { 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_FFP, UNIT_FFP, "FFP", "FFP", &cpu_set_opt, NULL, + (void *) UNIT_FFP }, + { UNIT_FFP, 0, "no FFP", "NOFFP", &cpu_set_opt, NULL, + (void *) UNIT_FFP }, + { MTAB_XTD | MTAB_VDV, 4096, NULL, "4K", &cpu_set_size }, + { MTAB_XTD | MTAB_VDV, 8192, NULL, "8K", &cpu_set_size }, + { MTAB_XTD | MTAB_VDV, 16384, NULL, "16K", &cpu_set_size }, + { MTAB_XTD | MTAB_VDV, 32768, NULL, "32K", &cpu_set_size }, + { MTAB_XTD | MTAB_VDV, 65536, NULL, "64K", &cpu_set_size }, + { MTAB_XTD | MTAB_VDV, 131072, NULL, "128K", &cpu_set_size }, + { MTAB_XTD | MTAB_VDV, 262144, NULL, "256K", &cpu_set_size }, + { MTAB_XTD | MTAB_VDV, 524288, NULL, "512K", &cpu_set_size }, + { MTAB_XTD | MTAB_VDV, 1048576, NULL, "1024K", &cpu_set_size }, + { 0 } + }; DEVICE cpu_dev = { - "CPU", &cpu_unit, cpu_reg, cpu_mod, - 1, 8, PA_N_SIZE, 1, 8, 16, - &cpu_ex, &cpu_dep, &cpu_reset, - &cpu_boot, NULL, NULL }; - + "CPU", &cpu_unit, cpu_reg, cpu_mod, + 1, 8, PA_N_SIZE, 1, 8, 16, + &cpu_ex, &cpu_dep, &cpu_reset, + &cpu_boot, NULL, NULL + }; + /* Memory protect data structures - mp_dev MP device descriptor - mp_unit MP unit descriptor - mp_reg MP register list - mp_mod MP modifiers list + mp_dev MP device descriptor + mp_unit MP unit descriptor + mp_reg MP register list + mp_mod MP modifiers list */ UNIT mp_unit = { UDATA (NULL, UNIT_MP_SEL1, 0) }; REG mp_reg[] = { - { FLDATA (CTL, dev_ctl[PRO/32], INT_V (PRO)) }, - { FLDATA (FLG, dev_flg[PRO/32], INT_V (PRO)) }, - { FLDATA (FBF, dev_fbf[PRO/32], INT_V (PRO)) }, - { ORDATA (FR, mp_fence, 15) }, - { ORDATA (VR, mp_viol, 16) }, - { FLDATA (MEV, mp_mevff, 0) }, - { FLDATA (EVR, mp_evrff, 0) }, - { NULL } }; + { FLDATA (CTL, dev_ctl[PRO/32], INT_V (PRO)) }, + { FLDATA (FLG, dev_flg[PRO/32], INT_V (PRO)) }, + { FLDATA (FBF, dev_fbf[PRO/32], INT_V (PRO)) }, + { ORDATA (FR, mp_fence, 15) }, + { ORDATA (VR, mp_viol, 16) }, + { FLDATA (MEV, mp_mevff, 0) }, + { FLDATA (EVR, mp_evrff, 0) }, + { NULL } + }; MTAB mp_mod[] = { - { UNIT_MP_JSB, UNIT_MP_JSB, "JSB (W5) in", "JSBIN", NULL }, - { UNIT_MP_JSB, 0, "JSB (W5) out", "JSBOUT", NULL }, - { UNIT_MP_INT, UNIT_MP_INT, "INT (W6) in", "INTIN", NULL }, - { UNIT_MP_INT, 0, "INT (W6) out", "INTOUT", NULL }, - { UNIT_MP_SEL1, UNIT_MP_SEL1, "SEL1 (W7) in", "SEL1IN", NULL }, - { UNIT_MP_SEL1, 0, "SEL1 (W7) out", "SEL1OUT", NULL }, - { 0 } }; + { UNIT_MP_JSB, UNIT_MP_JSB, "JSB (W5) in", "JSBIN", NULL }, + { UNIT_MP_JSB, 0, "JSB (W5) out", "JSBOUT", NULL }, + { UNIT_MP_INT, UNIT_MP_INT, "INT (W6) in", "INTIN", NULL }, + { UNIT_MP_INT, 0, "INT (W6) out", "INTOUT", NULL }, + { UNIT_MP_SEL1, UNIT_MP_SEL1, "SEL1 (W7) in", "SEL1IN", NULL }, + { UNIT_MP_SEL1, 0, "SEL1 (W7) out", "SEL1OUT", NULL }, + { 0 } + }; DEVICE mp_dev = { - "MP", &mp_unit, mp_reg, mp_mod, - 1, 8, 1, 1, 8, 16, - NULL, NULL, &mp_reset, - NULL, NULL, NULL, - NULL, DEV_DISABLE | DEV_DIS }; + "MP", &mp_unit, mp_reg, mp_mod, + 1, 8, 1, 1, 8, 16, + NULL, NULL, &mp_reset, + NULL, NULL, NULL, + NULL, DEV_DISABLE | DEV_DIS + }; - /* DMA controller data structures - dmax_dev DMAx device descriptor - dmax_reg DMAx register list + 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)) }, - { FLDATA (CTLALT, dev_ctl[DMALT0/32], INT_V (DMALT0)) }, - { ORDATA (CW1, dmac[0].cw1, 16) }, - { ORDATA (CW2, dmac[0].cw2, 16) }, - { ORDATA (CW3, dmac[0].cw3, 16) }, - { NULL } }; + { 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)) }, + { FLDATA (CTLALT, dev_ctl[DMALT0/32], INT_V (DMALT0)) }, + { 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, - NULL, DEV_DISABLE }; + "DMA0", &dma0_unit, dma0_reg, NULL, + 1, 8, 1, 1, 8, 16, + NULL, NULL, &dma0_reset, + NULL, NULL, NULL, + NULL, DEV_DISABLE + }; 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)) }, - { FLDATA (CTLALT, dev_ctl[DMALT1/32], INT_V (DMALT1)) }, - { ORDATA (CW1, dmac[1].cw1, 16) }, - { ORDATA (CW2, dmac[1].cw2, 16) }, - { ORDATA (CW3, dmac[1].cw3, 16) }, - { NULL } }; + { 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)) }, + { FLDATA (CTLALT, dev_ctl[DMALT1/32], INT_V (DMALT1)) }, + { 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, - NULL, DEV_DISABLE }; - + "DMA1", &dma1_unit, dma1_reg, NULL, + 1, 8, 1, 1, 8, 16, + NULL, NULL, &dma1_reset, + NULL, NULL, NULL, + NULL, DEV_DISABLE + }; + /* Interrupt defer table */ static const int32 defer_tab[] = { 0, 1, 1, 1, 0, 0, 0, 1 }; @@ -656,63 +663,70 @@ 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 }; - + &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 */ -uint32 iotrap = 0; /* set after setjmp */ -t_stat reason; /* set after setjmp */ -int32 i, dev; /* temp */ -DEVICE *dptr; /* temp */ -DIB *dibp; /* temp */ +uint32 intrq, dmarq; /* set after setjmp */ +uint32 iotrap = 0; /* 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 */ +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 */ +err_PC = PC = PC & VAMASK; /* load local PC */ reason = 0; /* Restore I/O state */ if (mp_dev.flags & DEV_DIS) dtab[PRO] = NULL; -else dtab[PRO] = &proio; /* set up MP dispatch */ +else dtab[PRO] = &proio; /* set up MP dispatch */ if (dma0_dev.flags & DEV_DIS) dtab[DMA0] = dtab[DMALT0] = NULL; -else { dtab[DMA0] = &dmpio; /* set up DMA0 dispatch */ - dtab[DMALT0] = &dmsio; } +else { + dtab[DMA0] = &dmpio; /* set up DMA0 dispatch */ + dtab[DMALT0] = &dmsio; + } if (dma1_dev.flags & DEV_DIS) dtab[DMA1] = dtab[DMALT1] = NULL; -else { dtab[DMA1] = &dmpio; /* set up DMA1 dispatch */ - dtab[DMALT1] = &dmsio; } +else { + dtab[DMA1] = &dmpio; /* set up DMA1 dispatch */ + dtab[DMALT1] = &dmsio; + } -for (i = VARDEV; i <= I_DEVMASK; i++) dtab[i] = NULL; /* clr disp table */ -dev_cmd[0] = dev_cmd[0] & M_FXDEV; /* clear dynamic info */ +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_srq[0] = dev_srq[1] = 0; /* init svc requests */ +dev_srq[0] = dev_srq[1] = 0; /* init svc requests */ 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 */ - if (dibp->srq) { setSRQ (dev); } /* restore srq */ - dtab[dev] = dibp->iot; } } /* set I/O dispatch */ -sim_rtc_init (clk_delay (0)); /* recalibrate clock */ +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 */ + if (dibp->srq) { setSRQ (dev); } /* restore srq */ + dtab[dev] = dibp->iot; /* set I/O dispatch */ + } + } +sim_rtc_init (clk_delay (0)); /* recalibrate clock */ /* Abort handling @@ -723,28 +737,31 @@ sim_rtc_init (clk_delay (0)); /* recalibrate clock */ 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 */ - +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, absel, v1, t, skip; +while (reason == 0) { /* loop until halted */ + uint32 IR, MA, absel, v1, t, skip; -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 (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 (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 */ + } /* (From Dave Bryan) Unlike most other I/O devices, the MP flag flip-flop is cleared @@ -757,321 +774,331 @@ if (dmarq) { "When IAK occurs and IRQ5 is asserted, the FLAGBFF is cleared, FLAGFF clocked off at next T2, and IRQ5 will no longer occur." */ -if (intrq && ((intrq <= PRO) || !ion_defer)) { /* interrupt request? */ - iotrap = 1; /* I/O trap cell instr */ - clrFBF (intrq); /* clear flag buffer */ - if (intrq == PRO) clrFLG (PRO); /* MP flag follows fbuf */ - 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 */ + if (intrq && ((intrq <= PRO) || !ion_defer)) { /* interrupt request? */ + iotrap = 1; /* I/O trap cell instr */ + clrFBF (intrq); /* clear flag buffer */ + if (intrq == PRO) clrFLG (PRO); /* MP flag follows fbuf */ + 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 && /* any breakpoints? */ - sim_brk_test (PC, SWMASK ('E') | /* unconditional or */ - (dms_enb? (dms_ump? SWMASK ('U'): SWMASK ('S')): - SWMASK ('N')))) { /* or right type for DMS? */ - 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; } + else { /* normal instruction */ + iotrap = 0; + err_PC = PC; /* save PC for error */ + if (sim_brk_summ && /* any breakpoints? */ + sim_brk_test (PC, SWMASK ('E') | /* unconditional or */ + (dms_enb? (dms_ump? SWMASK ('U'): SWMASK ('S')): + SWMASK ('N')))) { /* or right type for DMS? */ + 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 + 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> */ - 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 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 */ - if ((mp_unit.flags & UNIT_MP_JSB) && /* MP if W7 (JSB) out */ - CTL (PRO) && (MA < mp_fence)) - ABORT (ABORT_PRO); - WriteW (MA, PC); /* store PC */ - PCQ_ENTRY; - PC = (MA + 1) & VAMASK; /* jump */ - if (IR & I_IA) ion_defer = 1; /* ind? defer intr */ - 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 */ + if ((mp_unit.flags & UNIT_MP_JSB) && /* MP if W7 (JSB) out */ + CTL (PRO) && (MA < mp_fence)) + ABORT (ABORT_PRO); + 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 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 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 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 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; -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 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 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 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 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 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 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 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; -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 */ + 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 */ + 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 */ - + 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 */ -case 0201: /* divide */ -case 0202: /* EAU group 2 */ -case 0210: /* DLD */ -case 0211: /* DST */ - reason = cpu_eau (IR, intrq); /* extended arith */ - break; + case 0200: /* EAU group 0 */ + case 0201: /* divide */ + case 0202: /* EAU group 2 */ + case 0210: /* DLD */ + case 0211: /* DST */ + reason = cpu_eau (IR, intrq); /* extended arith */ + break; /* Extended instructions */ -case 0212: /* UIG 0 extension */ - reason = cpu_uig_0 (IR, intrq); /* extended opcode */ - dmarq = calc_dma (); /* recalc DMA masks */ - intrq = calc_int (); /* recalc interrupts */ - break; + case 0212: /* UIG 0 extension */ + reason = cpu_uig_0 (IR, intrq); /* extended opcode */ + dmarq = calc_dma (); /* recalc DMA masks */ + intrq = calc_int (); /* recalc interrupts */ + break; -case 0203: /* UIG 1 extension */ -case 0213: - reason = cpu_uig_1 (IR, intrq); /* extended opcode */ - dmarq = calc_dma (); /* recalc DMA masks */ - intrq = calc_int (); /* recalc interrupts */ - break; } /* end case IR */ + case 0203: /* UIG 1 extension */ + case 0213: + reason = cpu_uig_1 (IR, intrq); /* extended opcode */ + dmarq = calc_dma (); /* recalc DMA masks */ + intrq = calc_int (); /* recalc interrupts */ + 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 */ + 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; -if (iotrap && (reason == STOP_HALT)) MR = intaddr; /* HLT in trap cell? */ -else MR = (PC - 1) & VAMASK; /* no, M = P - 1 */ -TR = ReadTAB (MR); /* last word fetched */ -if ((reason == STOP_RSRV) || (reason == STOP_IODV) || /* instr error? */ - (reason == STOP_IND)) PC = err_PC; /* back up PC */ -dms_upd_sr (); /* update dms_sr */ -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); - dibp->srq = SRQ (dev); } } -pcq_r->qptr = pcq_p; /* update pc q ptr */ +if (iotrap && (reason == STOP_HALT)) MR = intaddr; /* HLT in trap cell? */ +else MR = (PC - 1) & VAMASK; /* no, M = P - 1 */ +TR = ReadTAB (MR); /* last word fetched */ +if ((reason == STOP_RSRV) || (reason == STOP_IODV) || /* instr error? */ + (reason == STOP_IND)) PC = err_PC; /* back up PC */ +dms_upd_sr (); /* update dms_sr */ +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); + dibp->srq = SRQ (dev); + } + } +pcq_r->qptr = pcq_p; /* update pc q ptr */ return reason; } - + /* Resolve indirect addresses */ t_stat resolve (uint32 MA, uint32 *addr, uint32 irq) { uint32 i; -for (i = 0; (i < ind_max) && (MA & I_IA); i++) { /* resolve multilevel */ - if (irq && /* int req? */ - ((i >= 2) || (mp_unit.flags & UNIT_MP_INT)) && /* ind > 3 or W6 out? */ - !(mp_unit.flags & DEV_DIS)) /* MP installed? */ - return STOP_INDINT; /* break out */ - MA = ReadW (MA & VAMASK); } -if (i >= ind_max) return STOP_IND; /* indirect loop? */ +for (i = 0; (i < ind_max) && (MA & I_IA); i++) { /* resolve multilevel */ + if (irq && /* int req? */ + ((i >= 2) || (mp_unit.flags & UNIT_MP_INT)) && /* ind > 3 or W6 out? */ + !(mp_unit.flags & DEV_DIS)) /* MP installed? */ + return STOP_INDINT; /* break out */ + MA = ReadW (MA & VAMASK); + } +if (i >= ind_max) return STOP_IND; /* indirect loop? */ *addr = MA; return SCPE_OK; } @@ -1082,9 +1109,9 @@ t_stat Ea (uint32 IR, uint32 *addr, uint32 irq) { uint32 MA; -MA = IR & (I_IA | I_DISP); /* ind + disp */ -if (IR & I_CP) MA = ((PC - 1) & I_PAGENO) | MA; /* current page? */ -return resolve (MA, addr, irq); /* resolve indirects */ +MA = IR & (I_IA | I_DISP); /* ind + disp */ +if (IR & I_CP) MA = ((PC - 1) & I_PAGENO) | MA; /* current page? */ +return resolve (MA, addr, irq); /* resolve indirects */ } /* Shift micro operation */ @@ -1093,59 +1120,69 @@ 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 */ +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) && /* protected? */ - ((sop == ioHLT) || /* halt or !ovf? */ +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) && /* protected? */ + ((sop == ioHLT) || /* halt or !ovf? */ ((dev != OVF) && (mp_unit.flags & UNIT_MP_SEL1)))) { - 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) { /* halt? */ - int32 len = strlen (halt_msg); /* find end msg */ - sprintf (&halt_msg[len - 6], "%06o", ir); /* add the halt */ - return STOP_HALT; } -return (iodata >> IOT_V_REASON); /* return status */ + 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) { /* halt? */ + int32 len = strlen (halt_msg); /* find end msg */ + sprintf (&halt_msg[len - 6], "%06o", ir); /* add the halt */ + return STOP_HALT; + } +return (iodata >> IOT_V_REASON); /* return status */ } /* Device dispatch */ @@ -1162,10 +1199,10 @@ uint32 calc_dma (void) { uint32 r = 0; -if (CMD (DMA0) && SRQ (dmac[0].cw1 & I_DEVMASK)) /* check DMA0 cycle */ - r = r | DMAR0; -if (CMD (DMA1) && SRQ (dmac[1].cw1 & I_DEVMASK)) /* check DMA1 cycle */ - r = r | DMAR1; +if (CMD (DMA0) && SRQ (dmac[0].cw1 & I_DEVMASK)) /* check DMA0 cycle */ + r = r | DMAR0; +if (CMD (DMA1) && SRQ (dmac[1].cw1 & I_DEVMASK)) /* check DMA1 cycle */ + r = r | DMAR1; return r; } @@ -1193,30 +1230,38 @@ 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); } } +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) @@ -1295,7 +1340,7 @@ else return ReadIO (addr, dms_ump); checks are done (so, to pass, the page must be writable AND the target must be above the MP fence). */ -#define MP_TEST(x) (CTL (PRO) && ((x) > 1) && ((x) < mp_fence)) +#define MP_TEST(x) (CTL (PRO) && ((x) > 1) && ((x) < mp_fence)) void WriteB (uint32 va, uint32 dat) { @@ -1305,10 +1350,11 @@ if (dms_enb) pa = dms (va >> 1, dms_ump, WR); else pa = va >> 1; if (MP_TEST (va >> 1)) ABORT (ABORT_PRO); if (MEM_ADDR_OK (pa)) { - t = ReadPW (pa); - if (va & 1) t = (t & 0177400) | (dat & 0377); - else t = (t & 0377) | ((dat & 0377) << 8); - WritePW (pa, t); } + t = ReadPW (pa); + if (va & 1) t = (t & 0177400) | (dat & 0377); + else t = (t & 0377) | ((dat & 0377) << 8); + WritePW (pa, t); + } return; } @@ -1317,15 +1363,17 @@ void WriteBA (uint32 va, uint32 dat) uint32 pa, t; if (dms_enb) { - dms_viol (va >> 1, MVI_WPR); /* viol if prot */ - pa = dms (va >> 1, dms_ump ^ MAP_LNT, WR); } + dms_viol (va >> 1, MVI_WPR); /* viol if prot */ + pa = dms (va >> 1, dms_ump ^ MAP_LNT, WR); + } else pa = va >> 1; if (MP_TEST (va >> 1)) ABORT (ABORT_PRO); if (MEM_ADDR_OK (pa)) { - t = ReadPW (pa); - if (va & 1) t = (t & 0177400) | (dat & 0377); - else t = (t & 0377) | ((dat & 0377) << 8); - WritePW (pa, t); } + t = ReadPW (pa); + if (va & 1) t = (t & 0177400) | (dat & 0377); + else t = (t & 0377) | ((dat & 0377) << 8); + WritePW (pa, t); + } return; } @@ -1345,8 +1393,9 @@ 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); } + dms_viol (va, MVI_WPR); /* viol if prot */ + pa = dms (va, dms_ump ^ MAP_LNT, WR); + } else pa = va; if (MP_TEST (va)) ABORT (ABORT_PRO); if (MEM_ADDR_OK (pa)) WritePW (pa, dat); @@ -1369,24 +1418,26 @@ if (pa <= 1) ABREG[pa] = dat & DMASK; else M[pa] = dat & DMASK; 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); /* prot violation? */ +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); /* prot violation? */ return (MAP_GETPAG (mpr) | VA_GETOFF (va)); } @@ -1396,15 +1447,17 @@ 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 */ +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 (MAP_GETPAG (mpr) | VA_GETOFF (va)); } @@ -1414,31 +1467,33 @@ uint32 dms_cons (uint32 va, int32 sw) { uint32 map_sel; -if (sw & SWMASK ('V')) map_sel = dms_ump; /* switch? select map */ +if (sw & SWMASK ('V')) map_sel = dms_ump; /* switch? select map */ else if (sw & SWMASK ('S')) map_sel = SMAP; else if (sw & SWMASK ('U')) map_sel = UMAP; else if (sw & SWMASK ('P')) map_sel = PAMAP; else if (sw & SWMASK ('Q')) map_sel = PBMAP; -else return va; /* no switch, physical */ -if (va >= VASIZE) return MEMSIZE; /* virtual, must be 15b */ -else if (dms_enb) return dms_io (va, map_sel); /* DMS on? go thru map */ -else return va; /* else return virtual */ +else return va; /* no switch, physical */ +if (va >= VASIZE) return MEMSIZE; /* virtual, must be 15b */ +else if (dms_enb) return dms_io (va, map_sel); /* DMS on? go thru map */ +else return va; /* else return virtual */ } /* Mem protect and DMS validation for jumps */ void mp_dms_jmp (uint32 va) { -uint32 pgn = VA_GETPAG (va); /* get page num */ +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 */ +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; } @@ -1462,12 +1517,13 @@ return; 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 */ + ((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; } @@ -1481,7 +1537,7 @@ 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 NOTE: LIx/MIx reads floating I/O bus (0 on all machines). @@ -1507,29 +1563,38 @@ 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; - break; -case ioSFS: /* skip flag set */ - if (ion) PC = (PC + 1) & VAMASK; - break; -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 */ +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; + break; + + case ioSFS: /* skip flag set */ + if (ion) PC = (PC + 1) & VAMASK; + break; + + 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; } @@ -1539,44 +1604,58 @@ return dat; 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 */ - if (UNIT_CPU_TYPE != UNIT_TYPE_211X) SR = dat; - break; -default: - break; } -if (IR & I_HC) O = 0; /* HC option */ +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 */ + if (UNIT_CPU_TYPE != UNIT_TYPE_211X) 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; } +switch (inst) { /* case on opcode */ + + case ioMIX: /* merge */ + dat = dat | intaddr; + break; + + case ioLIX: /* load */ + dat = intaddr; + break; + + default: + break; + } + return dat; } @@ -1588,60 +1667,77 @@ return dat; int32 proio (int32 inst, int32 IR, int32 dat) { -switch (inst) { /* case on opcode */ -case ioSFC: /* skip flag clear */ - if (!mp_mevff) PC = (PC + 1) & VAMASK; /* skip if mem prot */ - break; -case ioSFS: /* skip flag set */ - if (mp_mevff) PC = (PC + 1) & VAMASK; /* skip if DMS */ - break; -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 */ +switch (inst) { /* case on opcode */ + + case ioSFC: /* skip flag clear */ + if (!mp_mevff) PC = (PC + 1) & VAMASK; /* skip if mem prot */ + break; + + case ioSFS: /* skip flag set */ + if (mp_mevff) PC = (PC + 1) & VAMASK; /* skip if DMS */ + break; + + 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; } +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; } @@ -1653,39 +1749,51 @@ 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; - break; -case ioSFS: /* skip flag set */ - if (FLG (DMA0 + ch) != 0) PC = (PC + 1) & VAMASK; - break; -case ioLIX: /* load */ - dat = 0; -case ioMIX: /* merge */ - if (UNIT_CPU_TYPE == UNIT_TYPE_21MX) 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 */ +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; + break; + + case ioSFS: /* skip flag set */ + if (FLG (DMA0 + ch) != 0) PC = (PC + 1) & VAMASK; + break; + + case ioLIX: /* load */ + dat = 0; + case ioMIX: /* merge */ + if (UNIT_CPU_TYPE == UNIT_TYPE_21MX) 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. @@ -1702,66 +1810,76 @@ return dat; void dma_cycle (uint32 ch, uint32 map) { int32 temp, dev, MA; -int32 inp = dmac[ch].cw2 & DMA2_OI; /* input flag */ +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 */ +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 */ - if ((dmac[ch].cw1 & (DMA1_STC | DMA1_CLC)) == 0) - devdisp (dev, ioFLG, I_HC + dev, 0); /* clear flag */ - if (dmac[ch].cw1 & DMA1_STC) /* if STC flag, */ - devdisp (dev, ioCTL, I_HC + dev, 0); /* do STC,C dev */ - if (dmac[ch].cw1 & DMA1_CLC) /* CLC at end? */ - devdisp (dev, ioCTL, I_HC + I_CTL + dev, 0); /* yes */ - } /* end output */ - setFLG (DMA0 + ch); /* set DMA flg */ - clrCMD (DMA0 + ch); /* clr DMA cmd */ - devdisp (dev, ioEDT, dev, 0); /* do EDT */ - } +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 */ + if ((dmac[ch].cw1 & (DMA1_STC | DMA1_CLC)) == 0) + devdisp (dev, ioFLG, I_HC + dev, 0); /* clear flag */ + if (dmac[ch].cw1 & DMA1_STC) /* if STC flag, */ + devdisp (dev, ioCTL, I_HC + dev, 0); /* do STC,C dev */ + if (dmac[ch].cw1 & DMA1_CLC) /* CLC at end? */ + devdisp (dev, ioCTL, I_HC + I_CTL + dev, 0); /* yes */ + } /* end output */ + setFLG (DMA0 + ch); /* set DMA flg */ + clrCMD (DMA0 + ch); /* clr DMA cmd */ + devdisp (dev, ioEDT, dev, 0); /* do EDT */ + } return; } /* Unimplemented device routine NOTE: For SC < 10, LIx/MIx reads floating S-bus (-1 on 21MX, 0 on 2116/2100). - For SC >= 10, LIx/MIx reads floating I/O bus (0 on all machines). */ + For SC >= 10, LIx/MIx reads floating I/O bus (0 on all machines). */ int32 nulio (int32 inst, int32 IR, int32 dat) { int32 devd; -devd = IR & I_DEVMASK; /* get device no */ -switch (inst) { /* case on opcode */ -case ioSFC: /* skip flag clear */ - PC = (PC + 1) & VAMASK; - break; -case ioLIX: /* load */ - dat = 0; -case ioMIX: /* merge */ - if ((devd < VARDEV) && (UNIT_CPU_TYPE == UNIT_TYPE_21MX)) - dat = DMASK; - break; -default: - break; } +devd = IR & I_DEVMASK; /* get device no */ +switch (inst) { /* case on opcode */ + + case ioSFC: /* skip flag clear */ + PC = (PC + 1) & VAMASK; + break; + + case ioLIX: /* load */ + dat = 0; + + case ioMIX: /* merge */ + if ((devd < VARDEV) && (UNIT_CPU_TYPE == UNIT_TYPE_21MX)) + dat = DMASK; + break; + + default: + break; + } + return (stop_dev << IOT_V_REASON) | dat; } - + /* Reset routines */ t_stat cpu_reset (DEVICE *dptr) @@ -1774,7 +1892,7 @@ clrCTL (PWR); clrFLG (PWR); clrFBF (PWR); dev_srq[0] = dev_srq[0] & ~M_FXDEV; -dms_enb = dms_ump = 0; /* init DMS */ +dms_enb = dms_ump = 0; /* init DMS */ dms_sr = 0; dms_vr = 0; pcq_r = find_reg ("PCQ", NULL, dptr); @@ -1784,7 +1902,7 @@ if (M == NULL) M = calloc (PASIZE, sizeof (uint16)); if (M == NULL) return SCPE_MEM; if (pcq_r) pcq_r->qptr = 0; else return SCPE_IERR; -sim_vm_post = &hp_post_cmd; /* set cmd post proc */ +sim_vm_post = &hp_post_cmd; /* set cmd post proc */ return SCPE_OK; } @@ -1793,7 +1911,7 @@ t_stat mp_reset (DEVICE *dptr) clrCTL (PRO); clrFLG (PRO); clrFBF (PRO); -mp_fence = 0; /* init mprot */ +mp_fence = 0; /* init mprot */ mp_viol = 0; mp_mevff = 0; mp_evrff = 1; @@ -1802,27 +1920,27 @@ return SCPE_OK; t_stat dma0_reset (DEVICE *tptr) { -hp_enbdis_pair (&dma0_dev, &dma1_dev); /* make pair cons */ +hp_enbdis_pair (&dma0_dev, &dma1_dev); /* make pair cons */ clrCMD (DMA0); clrCTL (DMA0); setFLG (DMA0); clrSRQ (DMA0); clrCTL (DMALT0); -if (sim_switches & SWMASK ('P')) /* power up? */ - dmac[0].cw1 = dmac[0].cw2 = dmac[0].cw3 = 0; +if (sim_switches & SWMASK ('P')) /* power up? */ + dmac[0].cw1 = dmac[0].cw2 = dmac[0].cw3 = 0; return SCPE_OK; } t_stat dma1_reset (DEVICE *tptr) { -hp_enbdis_pair (&dma1_dev, &dma0_dev); /* make pair cons */ +hp_enbdis_pair (&dma1_dev, &dma0_dev); /* make pair cons */ clrCMD (DMA1); clrCTL (DMA1); setFLG (DMA1); clrSRQ (DMA1); clrCTL (DMALT1); -if (sim_switches & SWMASK ('P')) /* power up? */ - dmac[1].cw1 = dmac[1].cw2 = dmac[1].cw3 = 0; +if (sim_switches & SWMASK ('P')) /* power up? */ + dmac[1].cw1 = dmac[1].cw2 = dmac[1].cw3 = 0; return SCPE_OK; } @@ -1861,17 +1979,18 @@ int32 mc = 0; uint32 i; if ((val <= 0) || (val > PASIZE) || ((val & 07777) != 0) || - ((UNIT_CPU_TYPE != UNIT_TYPE_21MX) && (val > VASIZE))) - return SCPE_ARG; -if (!(sim_switches & SWMASK ('F'))) { /* force truncation? */ + ((UNIT_CPU_TYPE != UNIT_TYPE_21MX) && (val > VASIZE))) + return SCPE_ARG; +if (!(sim_switches & SWMASK ('F'))) { /* force truncation? */ for (i = val; i < MEMSIZE; i++) mc = mc | M[i]; if ((mc != 0) && (!get_yn ("Really truncate memory [N]?", FALSE))) - return SCPE_INCOMP; } + return SCPE_INCOMP; + } 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) @@ -1923,7 +2042,7 @@ return; void hp_post_cmd (t_bool from_scp) { -TR = ReadTAB (MR); /* sync T with M */ +TR = ReadTAB (MR); /* sync T with M */ return; } @@ -1936,19 +2055,23 @@ DIB *dibp, *chkp; uint32 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; } } } } + 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; } @@ -1969,25 +2092,28 @@ uint32 mod; mod = MOD_CURRENT; for (i = 0; opt_val[i].cpuf != 0; i++) { - if ((opt == opt_val[i].optf) && (mod & opt_val[i].cpuf)) { - if (mod == MOD_2100) - if ((opt == UNIT_FP) || (opt == UNIT_FFP)) - uptr->flags = uptr->flags & ~UNIT_IOP; - else if (opt == UNIT_IOP) - uptr->flags = uptr->flags & ~(UNIT_FP | UNIT_FFP); - if (opt == TYPE_211X) - mp_dev.flags = mp_dev.flags | DEV_DIS; - else if ((opt == UNIT_DMS) || (opt == TYPE_2100) || (opt == TYPE_21MX)) - mp_dev.flags = mp_dev.flags & ~DEV_DIS; - if ((opt == TYPE_211X) || (opt == TYPE_2100) || (opt == TYPE_21MX)) { - dma0_dev.flags = dma0_dev.flags & ~DEV_DIS; - dma1_dev.flags = dma1_dev.flags & ~DEV_DIS; } - if (((opt == TYPE_211X) || (opt == TYPE_2100)) && (MEMSIZE > VASIZE)) - return cpu_set_size (uptr, VASIZE, cptr, desc); - return SCPE_OK; } } + if ((opt == opt_val[i].optf) && (mod & opt_val[i].cpuf)) { + if (mod == MOD_2100) + if ((opt == UNIT_FP) || (opt == UNIT_FFP)) + uptr->flags = uptr->flags & ~UNIT_IOP; + else if (opt == UNIT_IOP) + uptr->flags = uptr->flags & ~(UNIT_FP | UNIT_FFP); + if (opt == TYPE_211X) + mp_dev.flags = mp_dev.flags | DEV_DIS; + else if ((opt == UNIT_DMS) || (opt == TYPE_2100) || (opt == TYPE_21MX)) + mp_dev.flags = mp_dev.flags & ~DEV_DIS; + if ((opt == TYPE_211X) || (opt == TYPE_2100) || (opt == TYPE_21MX)) { + dma0_dev.flags = dma0_dev.flags & ~DEV_DIS; + dma1_dev.flags = dma1_dev.flags & ~DEV_DIS; + } + if (((opt == TYPE_211X) || (opt == TYPE_2100)) && (MEMSIZE > VASIZE)) + return cpu_set_size (uptr, VASIZE, cptr, desc); + return SCPE_OK; + } + } return SCPE_NOFNC; } - + /* IBL routine (CPU boot) */ t_stat cpu_boot (int32 unitno, DEVICE *dptr) @@ -1999,18 +2125,24 @@ int32 sel = (SR >> IBL_V_SEL) & IBL_M_SEL; if (dev < 010) return SCPE_NOFNC; switch (sel) { -case 0: /* PTR boot */ - ibl_copy (ptr_rom, dev); - break; -case 1: /* DP/DQ boot */ - ibl_copy (dq_rom, dev); - break; -case 2: /* MS boot */ - ibl_copy (ms_rom, dev); - break; -case 3: /* DS boot */ - ibl_copy (ds_rom,dev); - break; } + + case 0: /* PTR boot */ + ibl_copy (ptr_rom, dev); + break; + + case 1: /* DP/DQ boot */ + ibl_copy (dq_rom, dev); + break; + + case 2: /* MS boot */ + ibl_copy (ms_rom, dev); + break; + + case 3: /* DS boot */ + ibl_copy (ds_rom,dev); + break; + } + return SCPE_OK; } @@ -2031,17 +2163,18 @@ t_stat ibl_copy (const uint16 pboot[IBL_LNT], int32 dev) int32 i; uint16 wd; -if (dev < 010) return SCPE_ARG; /* valid device? */ -PC = ((MEMSIZE - 1) & ~IBL_MASK) & VAMASK; /* start at mem top */ -for (i = 0; i < IBL_LNT; i++) { /* copy bootstrap */ - wd = pboot[i]; /* get word */ - if (((wd & I_NMRMASK) == I_IO) && /* IO instruction? */ - ((wd & I_DEVMASK) >= 010) && /* dev >= 10? */ - (I_GETIOOP (wd) != ioHLT)) /* not a HALT? */ - M[PC + i] = (wd + (dev - 010)) & DMASK; /* change dev code */ - else M[PC + i] = wd; } /* leave unchanged */ -M[PC + IBL_DPC] = (M[PC + IBL_DPC] + (dev - 010)) & DMASK; /* patch DMA ctrl */ -M[PC + IBL_END] = (~PC + 1) & DMASK; /* fill in start of boot */ +if (dev < 010) return SCPE_ARG; /* valid device? */ +PC = ((MEMSIZE - 1) & ~IBL_MASK) & VAMASK; /* start at mem top */ +for (i = 0; i < IBL_LNT; i++) { /* copy bootstrap */ + wd = pboot[i]; /* get word */ + if (((wd & I_NMRMASK) == I_IO) && /* IO instruction? */ + ((wd & I_DEVMASK) >= 010) && /* dev >= 10? */ + (I_GETIOOP (wd) != ioHLT)) /* not a HALT? */ + M[PC + i] = (wd + (dev - 010)) & DMASK; /* change dev code */ + else M[PC + i] = wd; /* leave unchanged */ + } +M[PC + IBL_DPC] = (M[PC + IBL_DPC] + (dev - 010)) & DMASK; /* patch DMA ctrl */ +M[PC + IBL_END] = (~PC + 1) & DMASK; /* fill in start of boot */ return SCPE_OK; } diff --git a/HP2100/hp2100_cpu.h b/HP2100/hp2100_cpu.h index 6a39ebfd..7a034be1 100644 --- a/HP2100/hp2100_cpu.h +++ b/HP2100/hp2100_cpu.h @@ -23,8 +23,8 @@ 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-Jan-05 JDB Reorganized CPU option flags - 14-Jan-05 RMS Cloned from hp2100_cpu.c + 21-Jan-05 JDB Reorganized CPU option flags + 14-Jan-05 RMS Cloned from hp2100_cpu.c CPU models are broken down into type and series to facilitate option validation. Bits 3:2 encode the type, and bits 1:0 encode the series @@ -32,56 +32,56 @@ */ #ifndef _HP2100_CPU_H_ -#define _HP2100_CPU_H_ 0 +#define _HP2100_CPU_H_ 0 -#define CPU_V_SERIES 0 -#define CPU_V_TYPE 2 +#define CPU_V_SERIES 0 +#define CPU_V_TYPE 2 -#define TYPE_211X 0 /* 2114, 2115, 2116 */ -#define TYPE_2100 1 /* 2100A, 2100S */ -#define TYPE_21MX 2 /* 21MX-M, 21MX-E, 21MX-F */ -#define TYPE_1000A 3 /* A600, A700, A900, A990 */ +#define TYPE_211X 0 /* 2114, 2115, 2116 */ +#define TYPE_2100 1 /* 2100A, 2100S */ +#define TYPE_21MX 2 /* 21MX-M, 21MX-E, 21MX-F */ +#define TYPE_1000A 3 /* A600, A700, A900, A990 */ -#define CPU_2116 (TYPE_211X << CPU_V_TYPE | 0) -#define CPU_2100 (TYPE_2100 << CPU_V_TYPE | 0) -#define CPU_21MX_M (TYPE_21MX << CPU_V_TYPE | 0) -#define CPU_21MX_E (TYPE_21MX << CPU_V_TYPE | 1) +#define CPU_2116 (TYPE_211X << CPU_V_TYPE | 0) +#define CPU_2100 (TYPE_2100 << CPU_V_TYPE | 0) +#define CPU_21MX_M (TYPE_21MX << CPU_V_TYPE | 0) +#define CPU_21MX_E (TYPE_21MX << CPU_V_TYPE | 1) -#define UNIT_V_CPU (UNIT_V_UF + 0) /* CPU model bits 0-3 */ -#define UNIT_M_CPU 017 /* CPU model mask */ -#define UNIT_M_TYPE 014 /* CPU type mask */ -#define UNIT_V_EAU (UNIT_V_UF + 4) /* EAU installed */ -#define UNIT_V_FP (UNIT_V_UF + 5) /* FP installed */ -#define UNIT_V_IOP (UNIT_V_UF + 6) /* IOP installed */ -#define UNIT_V_DMS (UNIT_V_UF + 7) /* DMS installed */ -#define UNIT_V_FFP (UNIT_V_UF + 8) /* FFP installed */ +#define UNIT_V_CPU (UNIT_V_UF + 0) /* CPU model bits 0-3 */ +#define UNIT_M_CPU 017 /* CPU model mask */ +#define UNIT_M_TYPE 014 /* CPU type mask */ +#define UNIT_V_EAU (UNIT_V_UF + 4) /* EAU installed */ +#define UNIT_V_FP (UNIT_V_UF + 5) /* FP installed */ +#define UNIT_V_IOP (UNIT_V_UF + 6) /* IOP installed */ +#define UNIT_V_DMS (UNIT_V_UF + 7) /* DMS installed */ +#define UNIT_V_FFP (UNIT_V_UF + 8) /* FFP installed */ -#define UNIT_CPU_MASK (UNIT_M_CPU << UNIT_V_CPU) -#define UNIT_2116 (CPU_2116 << UNIT_V_CPU) -#define UNIT_2100 (CPU_2100 << UNIT_V_CPU) -#define UNIT_21MX_M (CPU_21MX_M << UNIT_V_CPU) -#define UNIT_21MX_E (CPU_21MX_E << UNIT_V_CPU) +#define UNIT_CPU_MASK (UNIT_M_CPU << UNIT_V_CPU) +#define UNIT_2116 (CPU_2116 << UNIT_V_CPU) +#define UNIT_2100 (CPU_2100 << UNIT_V_CPU) +#define UNIT_21MX_M (CPU_21MX_M << UNIT_V_CPU) +#define UNIT_21MX_E (CPU_21MX_E << UNIT_V_CPU) -#define UNIT_TYPE_MASK (UNIT_M_TYPE << UNIT_V_CPU) -#define UNIT_TYPE_211X ((TYPE_211X << CPU_V_TYPE) << UNIT_V_CPU) -#define UNIT_TYPE_2100 ((TYPE_2100 << CPU_V_TYPE) << UNIT_V_CPU) -#define UNIT_TYPE_21MX ((TYPE_21MX << CPU_V_TYPE) << UNIT_V_CPU) +#define UNIT_TYPE_MASK (UNIT_M_TYPE << UNIT_V_CPU) +#define UNIT_TYPE_211X ((TYPE_211X << CPU_V_TYPE) << UNIT_V_CPU) +#define UNIT_TYPE_2100 ((TYPE_2100 << CPU_V_TYPE) << UNIT_V_CPU) +#define UNIT_TYPE_21MX ((TYPE_21MX << CPU_V_TYPE) << UNIT_V_CPU) -#define UNIT_CPU_MODEL (cpu_unit.flags & UNIT_CPU_MASK) -#define UNIT_CPU_TYPE (cpu_unit.flags & UNIT_TYPE_MASK) -#define CPU_TYPE (UNIT_CPU_TYPE >> (UNIT_V_CPU + CPU_V_TYPE)) +#define UNIT_CPU_MODEL (cpu_unit.flags & UNIT_CPU_MASK) +#define UNIT_CPU_TYPE (cpu_unit.flags & UNIT_TYPE_MASK) +#define CPU_TYPE (UNIT_CPU_TYPE >> (UNIT_V_CPU + CPU_V_TYPE)) -#define UNIT_EAU (1 << UNIT_V_EAU) -#define UNIT_FP (1 << UNIT_V_FP) -#define UNIT_IOP (1 << UNIT_V_IOP) -#define UNIT_DMS (1 << UNIT_V_DMS) -#define UNIT_FFP (1 << UNIT_V_FFP) +#define UNIT_EAU (1 << UNIT_V_EAU) +#define UNIT_FP (1 << UNIT_V_FP) +#define UNIT_IOP (1 << UNIT_V_IOP) +#define UNIT_DMS (1 << UNIT_V_DMS) +#define UNIT_FFP (1 << UNIT_V_FFP) -#define UNIT_OPTS (UNIT_EAU | UNIT_FP | UNIT_IOP | UNIT_DMS | UNIT_FFP) +#define UNIT_OPTS (UNIT_EAU | UNIT_FP | UNIT_IOP | UNIT_DMS | UNIT_FFP) -#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 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 t_stat resolve (uint32 MA, uint32 *addr, uint32 irq); uint8 ReadB (uint32 addr); diff --git a/HP2100/hp2100_cpu1.c b/HP2100/hp2100_cpu1.c index 5958d41f..fe15ae8f 100644 --- a/HP2100/hp2100_cpu1.c +++ b/HP2100/hp2100_cpu1.c @@ -19,24 +19,24 @@ 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 + 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. - CPU1 Extended arithmetic and optional microcode instructions + CPU1 Extended arithmetic and optional microcode instructions - 22-Feb-05 JDB Fixed missing MPCK on JRS target - Removed EXECUTE instruction (is NOP in actual microcode) - 18-Feb-05 JDB Add 2100/21MX Fast FORTRAN Processor instructions - 21-Jan-05 JDB Reorganized CPU option and operand processing flags - Split code along microcode modules - 15-Jan-05 RMS Cloned from hp2100_cpu.c + 22-Feb-05 JDB Fixed missing MPCK on JRS target + Removed EXECUTE instruction (is NOP in actual microcode) + 18-Feb-05 JDB Add 2100/21MX Fast FORTRAN Processor instructions + 21-Jan-05 JDB Reorganized CPU option and operand processing flags + Split code along microcode modules + 15-Jan-05 RMS Cloned from hp2100_cpu.c Primary references: - HP 1000 M/E/F-Series Computers Technical Reference Handbook - (5955-0282, Mar-1980) + (5955-0282, Mar-1980) - HP 1000 M/E/F-Series Computers Engineering and Reference Documentation - (92851-90001, Mar-1981) + (92851-90001, Mar-1981) Additional references are listed with the associated firmware implementations, as are the HP option model numbers pertaining to the @@ -85,7 +85,7 @@ instruction when the FFP firmware was not installed) resulted in a NOP. Under simulation, such execution causes an undefined instruction stop. */ - + #include #include "hp2100_defs.h" #include "hp2100_cpu.h" @@ -93,56 +93,56 @@ /* Operand processing encoding */ -#define OP_NUL 0 /* no operand */ -#define OP_CON 1 /* operand is a constant */ -#define OP_VAR 2 /* operand is a variable */ -#define OP_ADR 3 /* operand is an address */ -#define OP_ADK 4 /* op is addr of 1-word const */ -#define OP_ADF 5 /* op is addr of 2-word const */ -#define OP_ADX 6 /* op is addr of 3-word const */ -#define OP_ADT 7 /* op is addr of 4-word const */ +#define OP_NUL 0 /* no operand */ +#define OP_CON 1 /* operand is a constant */ +#define OP_VAR 2 /* operand is a variable */ +#define OP_ADR 3 /* operand is an address */ +#define OP_ADK 4 /* op is addr of 1-word const */ +#define OP_ADF 5 /* op is addr of 2-word const */ +#define OP_ADX 6 /* op is addr of 3-word const */ +#define OP_ADT 7 /* op is addr of 4-word const */ -#define OP_N_FLAGS 3 /* number of flag bits */ -#define OP_M_FLAGS ((1 << OP_N_FLAGS) - 1) /* mask for flag bits */ +#define OP_N_FLAGS 3 /* number of flag bits */ +#define OP_M_FLAGS ((1 << OP_N_FLAGS) - 1) /* mask for flag bits */ -#define OP_N_F 4 /* number of op fields */ +#define OP_N_F 4 /* number of op fields */ -#define OP_V_F1 (0 * OP_N_FLAGS) /* 1st operand field */ -#define OP_V_F2 (1 * OP_N_FLAGS) /* 2nd operand field */ -#define OP_V_F3 (2 * OP_N_FLAGS) /* 3rd operand field */ -#define OP_V_F4 (3 * OP_N_FLAGS) /* 4th operand field */ +#define OP_V_F1 (0 * OP_N_FLAGS) /* 1st operand field */ +#define OP_V_F2 (1 * OP_N_FLAGS) /* 2nd operand field */ +#define OP_V_F3 (2 * OP_N_FLAGS) /* 3rd operand field */ +#define OP_V_F4 (3 * OP_N_FLAGS) /* 4th operand field */ /* Operand patterns */ -#define OP_N (OP_NUL) -#define OP_C (OP_CON << OP_V_F1) -#define OP_V (OP_VAR << OP_V_F1) -#define OP_A (OP_ADR << OP_V_F1) -#define OP_K (OP_ADK << OP_V_F1) -#define OP_F (OP_ADF << OP_V_F1) -#define OP_CV ((OP_CON << OP_V_F1) | (OP_VAR << OP_V_F2)) -#define OP_AC ((OP_ADR << OP_V_F1) | (OP_CON << OP_V_F2)) -#define OP_AA ((OP_ADR << OP_V_F1) | (OP_ADR << OP_V_F2)) -#define OP_AK ((OP_ADR << OP_V_F1) | (OP_ADK << OP_V_F2)) -#define OP_AX ((OP_ADR << OP_V_F1) | (OP_ADX << OP_V_F2)) -#define OP_KV ((OP_ADK << OP_V_F1) | (OP_VAR << OP_V_F2)) -#define OP_KA ((OP_ADK << OP_V_F1) | (OP_ADR << OP_V_F2)) -#define OP_KK ((OP_ADK << OP_V_F1) | (OP_ADK << OP_V_F2)) -#define OP_CVA ((OP_CON << OP_V_F1) | (OP_VAR << OP_V_F2) | \ - (OP_ADR << OP_V_F3)) -#define OP_AAF ((OP_ADR << OP_V_F1) | (OP_ADR << OP_V_F2) | \ - (OP_ADF << OP_V_F3)) -#define OP_AAX ((OP_ADR << OP_V_F1) | (OP_ADR << OP_V_F2) | \ - (OP_ADX << OP_V_F3)) -#define OP_AXX ((OP_ADR << OP_V_F1) | (OP_ADX << OP_V_F2) | \ - (OP_ADX << OP_V_F3)) -#define OP_AAXX ((OP_ADR << OP_V_F1) | (OP_ADR << OP_V_F2) | \ - (OP_ADX << OP_V_F3) | (OP_ADX << OP_V_F4)) -#define OP_KKKK ((OP_ADK << OP_V_F1) | (OP_ADK << OP_V_F2) | \ - (OP_ADK << OP_V_F3) | (OP_ADK << OP_V_F4)) +#define OP_N (OP_NUL) +#define OP_C (OP_CON << OP_V_F1) +#define OP_V (OP_VAR << OP_V_F1) +#define OP_A (OP_ADR << OP_V_F1) +#define OP_K (OP_ADK << OP_V_F1) +#define OP_F (OP_ADF << OP_V_F1) +#define OP_CV ((OP_CON << OP_V_F1) | (OP_VAR << OP_V_F2)) +#define OP_AC ((OP_ADR << OP_V_F1) | (OP_CON << OP_V_F2)) +#define OP_AA ((OP_ADR << OP_V_F1) | (OP_ADR << OP_V_F2)) +#define OP_AK ((OP_ADR << OP_V_F1) | (OP_ADK << OP_V_F2)) +#define OP_AX ((OP_ADR << OP_V_F1) | (OP_ADX << OP_V_F2)) +#define OP_KV ((OP_ADK << OP_V_F1) | (OP_VAR << OP_V_F2)) +#define OP_KA ((OP_ADK << OP_V_F1) | (OP_ADR << OP_V_F2)) +#define OP_KK ((OP_ADK << OP_V_F1) | (OP_ADK << OP_V_F2)) +#define OP_CVA ((OP_CON << OP_V_F1) | (OP_VAR << OP_V_F2) | \ + (OP_ADR << OP_V_F3)) +#define OP_AAF ((OP_ADR << OP_V_F1) | (OP_ADR << OP_V_F2) | \ + (OP_ADF << OP_V_F3)) +#define OP_AAX ((OP_ADR << OP_V_F1) | (OP_ADR << OP_V_F2) | \ + (OP_ADX << OP_V_F3)) +#define OP_AXX ((OP_ADR << OP_V_F1) | (OP_ADX << OP_V_F2) | \ + (OP_ADX << OP_V_F3)) +#define OP_AAXX ((OP_ADR << OP_V_F1) | (OP_ADR << OP_V_F2) | \ + (OP_ADX << OP_V_F3) | (OP_ADX << OP_V_F4)) +#define OP_KKKK ((OP_ADK << OP_V_F1) | (OP_ADK << OP_V_F2) | \ + (OP_ADK << OP_V_F3) | (OP_ADK << OP_V_F4)) -typedef uint32 OP_PAT; /* operand pattern */ -typedef uint32 OPS[OP_N_F * 2]; /* operand array */ +typedef uint32 OP_PAT; /* operand pattern */ +typedef uint32 OPS[OP_N_F * 2]; /* operand array */ extern uint16 ABREG[2]; extern uint32 PC; @@ -163,26 +163,26 @@ extern uint32 pcq_p; extern uint32 stop_inst; extern UNIT cpu_unit; -t_stat cpu_eau (uint32 IR, uint32 intrq); /* EAU group handler */ -t_stat cpu_uig_0 (uint32 IR, uint32 intrq); /* UIG group 0 handler */ -t_stat cpu_uig_1 (uint32 IR, uint32 intrq); /* UIG group 1 handler */ +t_stat cpu_eau (uint32 IR, uint32 intrq); /* EAU group handler */ +t_stat cpu_uig_0 (uint32 IR, uint32 intrq); /* UIG group 0 handler */ +t_stat cpu_uig_1 (uint32 IR, uint32 intrq); /* UIG group 1 handler */ -static t_stat cpu_fp (uint32 IR, uint32 intrq); /* Floating-point */ -static t_stat cpu_ffp (uint32 IR, uint32 intrq); /* Fast FORTRAN Processor */ -static t_stat cpu_iop (uint32 IR, uint32 intrq); /* 2000 I/O Processor */ -static t_stat cpu_dms (uint32 IR, uint32 intrq); /* Dynamic mapping system */ -static t_stat cpu_eig (uint32 IR, uint32 intrq); /* Extended instruction group */ -static t_stat get_ops (OP_PAT pattern, OPS op, uint32 irq); /* operand processor */ +static t_stat cpu_fp (uint32 IR, uint32 intrq); /* Floating-point */ +static t_stat cpu_ffp (uint32 IR, uint32 intrq); /* Fast FORTRAN Processor */ +static t_stat cpu_iop (uint32 IR, uint32 intrq); /* 2000 I/O Processor */ +static t_stat cpu_dms (uint32 IR, uint32 intrq); /* Dynamic mapping system */ +static t_stat cpu_eig (uint32 IR, uint32 intrq); /* Extended instruction group */ +static t_stat get_ops (OP_PAT pattern, OPS op, uint32 irq); /* operand processor */ + +extern uint32 f_as (uint32 op, t_bool sub); /* FAD/FSB */ +extern uint32 f_mul (uint32 op); /* FMP */ +extern uint32 f_div (uint32 op); /* FDV */ +extern uint32 f_fix (void); /* FIX */ +extern uint32 f_flt (void); /* FLT */ +extern uint32 f_pack (int32 expon); /* .PACK helper */ +extern void f_unpack (void); /* .FLUN helper */ +extern void f_pwr2 (int32 n); /* .PWR2 helper */ -extern uint32 f_as (uint32 op, t_bool sub); /* FAD/FSB */ -extern uint32 f_mul (uint32 op); /* FMP */ -extern uint32 f_div (uint32 op); /* FDV */ -extern uint32 f_fix (void); /* FIX */ -extern uint32 f_flt (void); /* FLT */ -extern uint32 f_pack (int32 expon); /* .PACK helper */ -extern void f_unpack (void); /* .FLUN helper */ -extern void f_pwr2 (int32 n); /* .PWR2 helper */ - /* EAU The Extended Arithmetic Unit (EAU) adds ten instructions with double-word @@ -196,20 +196,20 @@ extern void f_pwr2 (int32 n); /* .PWR2 helper */ The instruction codes are mapped to routines as follows: Instr. Bits - Code 15-8 7-4 2116 2100 21MX-M 21MX-E 21MX-F Note + Code 15-8 7-4 2116 2100 21MX-M 21MX-E 21MX-F Note ------ ---- --- ------ ------ ------ ------ ------ --------------------- - 100000 200 00 DIAG DIAG Unsupported - 100020 200 01 ASL ASL ASL ASL ASL Bits 3-0 encode shift - 100040 200 02 LSL LSL LSL LSL LSL Bits 3-0 encode shift - 100060 200 03 TIMER TIMER Unsupported - 100100 200 04 RRL RRL RRL RRL RRL Bits 3-0 encode shift - 100200 200 10 MPY MPY MPY MPY MPY - 100400 201 xx DIV DIV DIV DIV DIV - 101020 202 01 ASR ASR ASR ASR ASR Bits 3-0 encode shift - 101040 202 02 LSR LSR LSR LSR LSR Bits 3-0 encode shift - 101100 202 04 RRR RRR RRR RRR RRR Bits 3-0 encode shift - 104200 210 xx DLD DLD DLD DLD DLD - 104400 211 xx DST DST DST DST DST + 100000 200 00 DIAG DIAG Unsupported + 100020 200 01 ASL ASL ASL ASL ASL Bits 3-0 encode shift + 100040 200 02 LSL LSL LSL LSL LSL Bits 3-0 encode shift + 100060 200 03 TIMER TIMER Unsupported + 100100 200 04 RRL RRL RRL RRL RRL Bits 3-0 encode shift + 100200 200 10 MPY MPY MPY MPY MPY + 100400 201 xx DIV DIV DIV DIV DIV + 101020 202 01 ASR ASR ASR ASR ASR Bits 3-0 encode shift + 101040 202 02 LSR LSR LSR LSR LSR Bits 3-0 encode shift + 101100 202 04 RRR RRR RRR RRR RRR Bits 3-0 encode shift + 104200 210 xx DLD DLD DLD DLD DLD + 104400 211 xx DST DST DST DST DST The remaining codes for bits 7-4 are undefined and will cause a simulator stop if enabled. On a real 21MX-M, all undefined instructions in the 200 @@ -220,7 +220,7 @@ extern void f_pwr2 (int32 n); /* .PWR2 helper */ EAU instruction decoding on the 21MX M-series is convoluted. The JEAU microorder maps IR bits 11, 9-7 and 5-4 to bits 2-0 of the microcode jump address. The map is detailed on page IC-84 of the ERD. - + The 21MX E/F-series add two undocumented instructions to the 200 group: TIMER and DIAG. These are described in the ERD on page IA 5-5, paragraph 5-7. The M-series executes these as MPY and RRL, respectively. A third @@ -240,156 +240,161 @@ OPS op; uint32 rs, qs, sc, v1, v2, t; int32 sop1, sop2; -if ((cpu_unit.flags & UNIT_EAU) == 0) return stop_inst; /* implemented? */ +if ((cpu_unit.flags & UNIT_EAU) == 0) return stop_inst; /* implemented? */ -switch ((IR >> 8) & 0377) { /* decode IR<15:8> */ +switch ((IR >> 8) & 0377) { /* decode IR<15:8> */ -case 0200: /* EAU group 0 */ - switch ((IR >> 4) & 017) { /* decode IR<7:4> */ + case 0200: /* EAU group 0 */ + switch ((IR >> 4) & 017) { /* decode IR<7:4> */ - case 000: /* DIAG 100000 */ - if (UNIT_CPU_MODEL != UNIT_21MX_E) /* must be 21MX-E */ - return stop_inst; /* trap if not */ - break; /* DIAG is NOP unless halted */ + case 000: /* DIAG 100000 */ + if (UNIT_CPU_MODEL != UNIT_21MX_E) /* must be 21MX-E */ + return stop_inst; /* trap if not */ + break; /* DIAG is NOP unless halted */ - case 001: /* ASL 100020-100037 */ - 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 001: /* ASL 100020-100037 */ + 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 100040-100057 */ - 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 002: /* LSL 100040-100057 */ + 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 100060 */ - if (UNIT_CPU_TYPE != UNIT_TYPE_21MX) /* must be 21MX */ - return stop_inst; /* trap if not */ - if (UNIT_CPU_MODEL == UNIT_21MX_M) /* 21MX M-series? */ - goto MPY; /* decode as MPY */ - BR = (BR + 1) & DMASK; /* increment B */ - if (BR) PC = err_PC; /* if !=0, repeat */ - break; + case 003: /* TIMER 100060 */ + if (UNIT_CPU_TYPE != UNIT_TYPE_21MX) /* must be 21MX */ + return stop_inst; /* trap if not */ + if (UNIT_CPU_MODEL == UNIT_21MX_M) /* 21MX M-series? */ + goto MPY; /* decode as MPY */ + BR = (BR + 1) & DMASK; /* increment B */ + if (BR) PC = err_PC; /* if !=0, repeat */ + break; - case 004: /* RRL 100100-100117 */ - 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 004: /* RRL 100100-100117 */ + 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 100200 */ - MPY: - if (reason = get_ops (OP_K, op, intrq)) /* get operand */ - break; - sop1 = SEXT (AR); /* sext AR */ - sop2 = SEXT (op[0]); /* sext mem */ - sop1 = sop1 * sop2; /* signed mpy */ - BR = (sop1 >> 16) & DMASK; /* to BR'AR */ - AR = sop1 & DMASK; - O = 0; /* no overflow */ - break; + case 010: /* MPY 100200 */ + MPY: + if (reason = get_ops (OP_K, op, intrq)) /* get operand */ + break; + sop1 = SEXT (AR); /* sext AR */ + sop2 = SEXT (op[0]); /* sext mem */ + sop1 = sop1 * sop2; /* signed mpy */ + BR = (sop1 >> 16) & DMASK; /* to BR'AR */ + AR = sop1 & DMASK; + O = 0; /* no overflow */ + break; - default: /* others undefined */ - return stop_inst; - } - - break; + default: /* others undefined */ + return stop_inst; + } + + break; -case 0201: /* DIV 100400 */ - if (reason = get_ops (OP_K, op, intrq)) /* get operand */ - break; - 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 = op[0]; /* 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 0201: /* DIV 100400 */ + if (reason = get_ops (OP_K, op, intrq)) /* get operand */ + break; + 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 = op[0]; /* 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 */ - switch ((IR >> 4) & 017) { /* decode IR<7:4> */ + case 0202: /* EAU group 2 */ + switch ((IR >> 4) & 017) { /* decode IR<7:4> */ - case 001: /* ASR 101020-101037 */ - 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 101040-101057 */ - 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 101100-101117 */ - 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: /* others undefined */ - return stop_inst; - } - - break; + case 001: /* ASR 101020-101037 */ + 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 101040-101057 */ + 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 101100-101117 */ + 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: /* others undefined */ + return stop_inst; + } + + break; -case 0210: /* DLD 104200 */ - if (reason = get_ops (OP_F, op, intrq)) /* get operand */ - break; - AR = (op[0] >> 16) & DMASK; /* load AR */ - BR = op[0] & DMASK; /* load BR */ - break; + case 0210: /* DLD 104200 */ + if (reason = get_ops (OP_F, op, intrq)) /* get operand */ + break; + AR = (op[0] >> 16) & DMASK; /* load AR */ + BR = op[0] & DMASK; /* load BR */ + break; -case 0211: /* DST 104400 */ - if (reason = get_ops (OP_A, op, intrq)) /* get operand */ - break; - WriteW (op[0], AR); /* store AR */ - op[0] = (op[0] + 1) & VAMASK; - WriteW (op[0], BR); /* store BR */ - break; + case 0211: /* DST 104400 */ + if (reason = get_ops (OP_A, op, intrq)) /* get operand */ + break; + WriteW (op[0], AR); /* store AR */ + op[0] = (op[0] + 1) & VAMASK; + WriteW (op[0], BR); /* store BR */ + break; -default: /* should never get here */ - return SCPE_IERR; - } + default: /* should never get here */ + return SCPE_IERR; + } return reason; } - + /* UIG 0 The first User Instruction Group (UIG) encodes firmware options for the 2100 and 21MX. Instruction codes 105000-105377 are assigned to microcode options as follows: - Instructions Option Name 2100 21MX-M 21MX-E 21MX-F + Instructions Option Name 2100 21MX-M 21MX-E 21MX-F ------------- ------------------------- ------ ------ ------ ------ - 105000-105362 2000 I/O Processor opt - - - - 105000-105120 Floating Point opt std std std - 105200-105237 Fast FORTRAN Processor opt opt opt std - 105240-105257 RTE-IVA/B EMA - - opt opt - 105240-105257 RTE-6/VMA - - opt opt - 105300-105317 Distributed System - - opt opt - 105340-105357 RTE-6/VM Operating System - - opt opt + 105000-105362 2000 I/O Processor opt - - - + 105000-105120 Floating Point opt std std std + 105200-105237 Fast FORTRAN Processor opt opt opt std + 105240-105257 RTE-IVA/B EMA - - opt opt + 105240-105257 RTE-6/VMA - - opt opt + 105300-105317 Distributed System - - opt opt + 105340-105357 RTE-6/VM Operating System - - opt opt Because the 2100 IOP microcode uses the same instruction range as the 2100 FP and FFP options, it cannot coexist with them. To simplify simulation, the @@ -403,93 +408,95 @@ return reason; t_stat cpu_uig_0 (uint32 IR, uint32 intrq) { if ((cpu_unit.flags & UNIT_IOP) && (UNIT_CPU_TYPE == UNIT_TYPE_2100)) { - if ((IR >= 0105020) && (IR <= 0105057)) /* remap LAI */ - IR = 0105400 | (IR - 0105020); - else if ((IR >= 0105060) && (IR <= 0105117)) /* remap SAI */ - IR = 0101400 | (IR - 0105060); - else - switch (IR) { /* remap others */ - case 0105000: IR = 0105470; break; /* ILIST */ - case 0105120: IR = 0105765; break; /* MBYTE (maps to MBT) */ - case 0105150: IR = 0105460; break; /* CRC */ - case 0105160: IR = 0105467; break; /* TRSLT */ - case 0105200: IR = 0105777; break; /* MWORD (maps to MVW) */ - case 0105220: IR = 0105462; break; /* READF */ - case 0105221: IR = 0105473; break; /* PRFIO */ - case 0105222: IR = 0105471; break; /* PRFEI */ - case 0105223: IR = 0105472; break; /* PRFEX */ - case 0105240: IR = 0105464; break; /* ENQ */ - case 0105257: IR = 0105465; break; /* PENQ */ - case 0105260: IR = 0105466; break; /* DEQ */ - case 0105300: IR = 0105764; break; /* SBYTE (maps to SBT) */ - case 0105320: IR = 0105763; break; /* LBYTE (maps to LBT) */ - case 0105340: IR = 0105461; break; /* REST */ - case 0105362: IR = 0105474; break; /* SAVE */ + if ((IR >= 0105020) && (IR <= 0105057)) /* remap LAI */ + IR = 0105400 | (IR - 0105020); + else if ((IR >= 0105060) && (IR <= 0105117)) /* remap SAI */ + IR = 0101400 | (IR - 0105060); + else { + switch (IR) { /* remap others */ + case 0105000: IR = 0105470; break; /* ILIST */ + case 0105120: IR = 0105765; break; /* MBYTE (maps to MBT) */ + case 0105150: IR = 0105460; break; /* CRC */ + case 0105160: IR = 0105467; break; /* TRSLT */ + case 0105200: IR = 0105777; break; /* MWORD (maps to MVW) */ + case 0105220: IR = 0105462; break; /* READF */ + case 0105221: IR = 0105473; break; /* PRFIO */ + case 0105222: IR = 0105471; break; /* PRFEI */ + case 0105223: IR = 0105472; break; /* PRFEX */ + case 0105240: IR = 0105464; break; /* ENQ */ + case 0105257: IR = 0105465; break; /* PENQ */ + case 0105260: IR = 0105466; break; /* DEQ */ + case 0105300: IR = 0105764; break; /* SBYTE (maps to SBT) */ + case 0105320: IR = 0105763; break; /* LBYTE (maps to LBT) */ + case 0105340: IR = 0105461; break; /* REST */ + case 0105362: IR = 0105474; break; /* SAVE */ - default: /* all others invalid */ - return stop_inst; - } - if (IR >= 0105700) return cpu_eig (IR, intrq); /* dispatch to 21MX EIG */ - else return cpu_iop (IR, intrq); } /* or to 21MX IOP */ + default: /* all others invalid */ + return stop_inst; + } + } + if (IR >= 0105700) return cpu_eig (IR, intrq); /* dispatch to 21MX EIG */ + else return cpu_iop (IR, intrq); /* or to 21MX IOP */ + } -switch ((IR >> 4) & 017) { /* decode IR<7:4> */ +switch ((IR >> 4) & 017) { /* decode IR<7:4> */ -case 000: /* 105000-105017 */ -case 001: /* 105020-105037 */ -case 002: /* 105040-105057 */ -case 003: /* 105060-105077 */ -case 004: /* 105100-105117 */ -case 005: /* 105120-105137 */ - return cpu_fp (IR, intrq); /* Floating Point */ + case 000: /* 105000-105017 */ + case 001: /* 105020-105037 */ + case 002: /* 105040-105057 */ + case 003: /* 105060-105077 */ + case 004: /* 105100-105117 */ + case 005: /* 105120-105137 */ + return cpu_fp (IR, intrq); /* Floating Point */ -case 010: /* 105200-105217 */ -case 011: /* 105220-105237 */ - return cpu_ffp (IR, intrq); /* Fast FORTRAN Processor */ - } + case 010: /* 105200-105217 */ + case 011: /* 105220-105237 */ + return cpu_ffp (IR, intrq); /* Fast FORTRAN Processor */ + } -return stop_inst; /* others undefined */ +return stop_inst; /* others undefined */ } - + /* UIG 1 The second User Instruction Group (UIG) encodes firmware options for the 21MX. Instruction codes 101400-101777 and 105400-105777 are assigned to microcode options as follows ("x" is "1" or "5" below): - Instructions Option Name 21MX-M 21MX-E 21MX-F - ------------- -------------------------- ------ ------ ------ - 10x400-10x437 2000 IOP opt opt - - 10x460-10x477 2000 IOP opt opt - - 10x700-10x737 Dynamic Mapping System opt opt std - 10x740-10x777 Extended Instruction Group std std std + Instructions Option Name 21MX-M 21MX-E 21MX-F + ------------- -------------------------- ------ ------ ------ + 10x400-10x437 2000 IOP opt opt - + 10x460-10x477 2000 IOP opt opt - + 10x700-10x737 Dynamic Mapping System opt opt std + 10x740-10x777 Extended Instruction Group std std std Only 21MX systems execute these instructions. */ t_stat cpu_uig_1 (uint32 IR, uint32 intrq) { -if (UNIT_CPU_TYPE != UNIT_TYPE_21MX) /* 21MX execution? */ - return stop_inst; /* no, so trap */ +if (UNIT_CPU_TYPE != UNIT_TYPE_21MX) /* 21MX execution? */ + return stop_inst; /* no, so trap */ -switch ((IR >> 4) & 017) { /* decode IR<7:4> */ +switch ((IR >> 4) & 017) { /* decode IR<7:4> */ -case 000: /* 105400-105417 */ -case 001: /* 105420-105437 */ -case 003: /* 105460-105477 */ - return cpu_iop (IR, intrq); /* 2000 I/O Processor */ + case 000: /* 105400-105417 */ + case 001: /* 105420-105437 */ + case 003: /* 105460-105477 */ + return cpu_iop (IR, intrq); /* 2000 I/O Processor */ -case 014: /* 105700-105717 */ -case 015: /* 105720-105737 */ - return cpu_dms (IR, intrq); /* Dynamic Mapping System */ + case 014: /* 105700-105717 */ + case 015: /* 105720-105737 */ + return cpu_dms (IR, intrq); /* Dynamic Mapping System */ -case 016: /* 105740-105737 */ -case 017: /* 105760-105777 */ - return cpu_eig (IR, intrq); /* Extended Instruction Group */ - } + case 016: /* 105740-105737 */ + case 017: /* 105760-105777 */ + return cpu_eig (IR, intrq); /* Extended Instruction Group */ + } -return stop_inst; /* others undefined */ +return stop_inst; /* others undefined */ } - + /* Floating Point The 2100 and 21MX CPUs share the single-precision (two word) floating point @@ -503,20 +510,21 @@ return stop_inst; /* others undefined */ Instr. 2100/21MX-M/E/F ------ --------------- - 105000 FAD - 105020 FSB - 105040 FMP - 105060 FDV - 105100 FIX - 105120 FLT + 105000 FAD + 105020 FSB + 105040 FMP + 105060 FDV + 105100 FIX + 105120 FLT Bits 3-0 are not decoded by these instructions, so FAD (e.g.) would be executed by any instruction in the range 105000-105017. */ static const OP_PAT op_fp[6] = { - OP_F, OP_F, OP_F, OP_F, /* FAD FSB FMP FDV */ - OP_N, OP_N }; /* FIX FLT --- --- */ + OP_F, OP_F, OP_F, OP_F, /* FAD FSB FMP FDV */ + OP_N, OP_N /* FIX FLT --- --- */ + }; static t_stat cpu_fp (uint32 IR, uint32 intrq) { @@ -524,48 +532,49 @@ t_stat reason = SCPE_OK; OPS op; uint32 entry; -if ((cpu_unit.flags & UNIT_FP) == 0) /* FP option installed? */ - return stop_inst; +if ((cpu_unit.flags & UNIT_FP) == 0) /* FP option installed? */ + return stop_inst; -entry = (IR >> 4) & 017; /* mask to entry point */ +entry = (IR >> 4) & 017; /* mask to entry point */ -if (op_fp[entry] != OP_N) - if (reason = get_ops (op_fp[entry], op, intrq)) /* get instruction operands */ - return reason; +if (op_fp[entry] != OP_N) { + if (reason = get_ops (op_fp[entry], op, intrq)) /* get instruction operands */ + return reason; + } -switch (entry) { /* decode IR<7:4> */ +switch (entry) { /* decode IR<7:4> */ -case 000: /* FMP 105000 */ - O = f_as (op[0], 0); /* add, upd ovflo */ - break; + case 000: /* FMP 105000 */ + O = f_as (op[0], 0); /* add, upd ovflo */ + break; -case 001: /* FMP 105020 */ - O = f_as (op[0], 1); /* sub, upd ovflo */ - break; + case 001: /* FMP 105020 */ + O = f_as (op[0], 1); /* sub, upd ovflo */ + break; -case 002: /* FMP 105040 */ - O = f_mul (op[0]); /* mul, upd ovflo */ - break; + case 002: /* FMP 105040 */ + O = f_mul (op[0]); /* mul, upd ovflo */ + break; -case 003: /* FDV 105060 */ - O = f_div (op[0]); /* div, upd ovflo */ - break; + case 003: /* FDV 105060 */ + O = f_div (op[0]); /* div, upd ovflo */ + break; -case 004: /* FIX 105100 */ - O = f_fix (); /* fix, upd ovflo */ - break; + case 004: /* FIX 105100 */ + O = f_fix (); /* fix, upd ovflo */ + break; -case 005: /* FLT 105120 */ - O = f_flt (); /* float, upd ovflo */ - break; + case 005: /* FLT 105120 */ + O = f_flt (); /* float, upd ovflo */ + break; -default: /* should be impossible */ - return SCPE_IERR; - } + default: /* should be impossible */ + return SCPE_IERR; + } return reason; } - + /* Fast FORTRAN Processor The Fast FORTRAN Processor (FFP) is a set of FORTRAN language accelerators @@ -604,25 +613,25 @@ return reason; Notes: 1. The "$SETP" instruction is sometimes listed as ".SETP" in the - documentation. + documentation. 2. Extended-precision arithmetic routines (e.g., .XMPY) exist on the - 21MX-F, but they are assigned instruction codes in the single-precision - floating-point module. + 21MX-F, but they are assigned instruction codes in the single-precision + floating-point module. 3. The software implementation of ..MAP supports 1-, 2-, or 3-dimensional - arrays, designated by setting A = -1, 0, and +1, respectively. The - firmware implementation supports only 2- and 3-dimensional access. - + arrays, designated by setting A = -1, 0, and +1, respectively. The + firmware implementation supports only 2- and 3-dimensional access. + 4. The documentation for ..MAP for the 2100 FFP shows A = 0 or -1 for two - or three dimensions, respectively, but the 21MX FFP shows A = 0 or +1. - The firmware actually only checks the LSB of A. + or three dimensions, respectively, but the 21MX FFP shows A = 0 or +1. + The firmware actually only checks the LSB of A. 5. The .DFER and .XFER implementations for the 2100 FFP return X+4 and Y+4 - in the A and B registers, whereas the 21MX FFP returns X+3 and Y+3. + in the A and B registers, whereas the 21MX FFP returns X+3 and Y+3. 6. The .XFER implementation for the 2100 FFP returns to P+2, whereas the - 21MX implementation returns to P+1. + 21MX implementation returns to P+1. Additional references: - DOS/RTE Relocatable Library Reference Manual (24998-90001, Oct-1981) @@ -630,14 +639,15 @@ return reason; */ static const OP_PAT op_ffp[32] = { - OP_N, OP_AAF, OP_AX, OP_AXX, /* --- DBLE SNGL .XMPY */ - OP_AXX, OP_AA, OP_A, OP_AAXX, /* .XDIV .DFER .XPAK XADD */ - OP_AAXX, OP_AAXX, OP_AAXX, OP_AXX, /* XSUB XMPY XDIV .XADD */ - OP_AXX, OP_A, OP_A, OP_AAX, /* .XSUB .XCOM ..DCM DDINT */ - OP_N, OP_AK, OP_KKKK, OP_A, /* .XFER .GOTO ..MAP .ENTR */ - OP_A, OP_K, OP_N, OP_K, /* .ENTP .PWR2 .FLUN $SETP */ - OP_C, OP_AA, OP_N, OP_N, /* .PACK .CFER --- --- */ - OP_N, OP_N, OP_N, OP_N }; /* --- --- --- --- */ + OP_N, OP_AAF, OP_AX, OP_AXX, /* --- DBLE SNGL .XMPY */ + OP_AXX, OP_AA, OP_A, OP_AAXX, /* .XDIV .DFER .XPAK XADD */ + OP_AAXX, OP_AAXX, OP_AAXX, OP_AXX, /* XSUB XMPY XDIV .XADD */ + OP_AXX, OP_A, OP_A, OP_AAX, /* .XSUB .XCOM ..DCM DDINT */ + OP_N, OP_AK, OP_KKKK, OP_A, /* .XFER .GOTO ..MAP .ENTR */ + OP_A, OP_K, OP_N, OP_K, /* .ENTP .PWR2 .FLUN $SETP */ + OP_C, OP_AA, OP_N, OP_N, /* .PACK .CFER --- --- */ + OP_N, OP_N, OP_N, OP_N /* --- --- --- --- */ + }; static t_stat cpu_ffp (uint32 IR, uint32 intrq) { @@ -648,263 +658,281 @@ uint32 j, sa, sb, sc, da, dc, ra, MA; int32 i; XPN xop; -if ((cpu_unit.flags & UNIT_FFP) == 0) /* FFP option installed? */ - return stop_inst; +if ((cpu_unit.flags & UNIT_FFP) == 0) /* FFP option installed? */ + return stop_inst; -entry = IR & 037; /* mask to entry point */ +entry = IR & 037; /* mask to entry point */ -if (op_ffp[entry] != OP_N) - if (reason = get_ops (op_ffp[entry], op, intrq))/* get instruction operands */ - return reason; +if (op_ffp[entry] != OP_N) { + if (reason = get_ops (op_ffp[entry], op, intrq)) /* get instruction operands */ + return reason; + } -switch (entry) { /* decode IR<3:0> */ +switch (entry) { /* decode IR<3:0> */ /* FFP module 1 */ -case 001: /* DBLE 105201 (OP_AAF) */ - WriteW (op[1]++, (op[2] >> 16) & DMASK); /* transfer high mantissa */ - WriteW (op[1]++, op[2] & 0177400); /* convert low mantissa */ - WriteW (op[1], op[2] & 0377); /* convert exponent */ - break; + case 001: /* DBLE 105201 (OP_AAF) */ + WriteW (op[1]++, (op[2] >> 16) & DMASK); /* transfer high mantissa */ + WriteW (op[1]++, op[2] & 0177400); /* convert low mantissa */ + WriteW (op[1], op[2] & 0377); /* convert exponent */ + break; -case 002: /* SNGL 105202 (OP_AX) */ - BR = op[2] >> 16; /* move LSB and expon to B */ - f_unpack (); /* unpack B into A/B */ - sa = AR; /* save exponent */ - AR = (op[1] >> 16) & DMASK; /* move MSB to A */ - BR = (op[1] & DMASK) | (BR != 0); /* move mid to B with carry */ - O = f_pack (SEXT (sa)); /* pack into A/B */ - break; + case 002: /* SNGL 105202 (OP_AX) */ + BR = op[2] >> 16; /* move LSB and expon to B */ + f_unpack (); /* unpack B into A/B */ + sa = AR; /* save exponent */ + AR = (op[1] >> 16) & DMASK; /* move MSB to A */ + BR = (op[1] & DMASK) | (BR != 0); /* move mid to B with carry */ + O = f_pack (SEXT (sa)); /* pack into A/B */ + break; #if defined (HAVE_INT64) -case 003: /* .XMPY 105203 (OP_AXX) */ - i = 0; /* params start at op[0] */ - goto XMPY; /* process as XMPY */ + case 003: /* .XMPY 105203 (OP_AXX) */ + i = 0; /* params start at op[0] */ + goto XMPY; /* process as XMPY */ -case 004: /* .XDIV 105204 (OP_AXX) */ - i = 0; /* params start at op[0] */ - goto XDIV; /* process as XDIV */ + case 004: /* .XDIV 105204 (OP_AXX) */ + i = 0; /* params start at op[0] */ + goto XDIV; /* process as XDIV */ #endif -case 005: /* .DFER 105205 (OP_AA) */ - BR = op[0]; /* get destination address */ - AR = op[1]; /* get source address */ - goto XFER; /* do transfer */ + case 005: /* .DFER 105205 (OP_AA) */ + BR = op[0]; /* get destination address */ + AR = op[1]; /* get source address */ + goto XFER; /* do transfer */ #if defined (HAVE_INT64) -case 006: /* .XPAK 105206 (OP_A) */ - if (UNIT_CPU_TYPE != UNIT_TYPE_21MX) /* must be 21MX */ - return stop_inst; /* trap if not */ - if (intrq) { /* interrupt pending? */ - PC = err_PC; /* restart instruction */ - break; } - xop = ReadX (op[0]); /* read unpacked */ - O = x_pak (&xop, xop, SEXT (AR)); /* pack mantissa, exponent */ - WriteX (op[0], xop); /* write back */ - break; + case 006: /* .XPAK 105206 (OP_A) */ + if (UNIT_CPU_TYPE != UNIT_TYPE_21MX) /* must be 21MX */ + return stop_inst; /* trap if not */ + if (intrq) { /* interrupt pending? */ + PC = err_PC; /* restart instruction */ + break; + } + xop = ReadX (op[0]); /* read unpacked */ + O = x_pak (&xop, xop, SEXT (AR)); /* pack mantissa, exponent */ + WriteX (op[0], xop); /* write back */ + break; -case 007: /* XADD 105207 (OP_AAXX) */ - i = 1; /* params start at op[1] */ -XADD: /* enter here from .XADD */ - if (intrq) { /* interrupt pending? */ - PC = err_PC; /* restart instruction */ - break; } - O = x_add (&xop, AS_XPN (op [i + 1]), AS_XPN (op [i + 3])); /* add ops */ - WriteX (op[i], xop); /* write sum */ - break; + case 007: /* XADD 105207 (OP_AAXX) */ + i = 1; /* params start at op[1] */ + XADD: /* enter here from .XADD */ + if (intrq) { /* interrupt pending? */ + PC = err_PC; /* restart instruction */ + break; + } + O = x_add (&xop, AS_XPN (op [i + 1]), AS_XPN (op [i + 3])); /* add ops */ + WriteX (op[i], xop); /* write sum */ + break; -case 010: /* XSUB 105210 (OP_AAXX) */ - i = 1; /* params start at op[1] */ -XSUB: /* enter here from .XSUB */ - if (intrq) { /* interrupt pending? */ - PC = err_PC; /* restart instruction */ - break; } - O = x_sub (&xop, AS_XPN (op [i + 1]), AS_XPN (op [i + 3])); /* subtract */ - WriteX (op[i], xop); /* write difference */ - break; + case 010: /* XSUB 105210 (OP_AAXX) */ + i = 1; /* params start at op[1] */ + XSUB: /* enter here from .XSUB */ + if (intrq) { /* interrupt pending? */ + PC = err_PC; /* restart instruction */ + break; + } + O = x_sub (&xop, AS_XPN (op [i + 1]), AS_XPN (op [i + 3])); /* subtract */ + WriteX (op[i], xop); /* write difference */ + break; -case 011: /* XMPY 105211 (OP_AAXX) */ - i = 1; /* params start at op[1] */ -XMPY: /* enter here from .XMPY */ - if (intrq) { /* interrupt pending? */ - PC = err_PC; /* restart instruction */ - break; } - O = x_mpy (&xop, AS_XPN (op [i + 1]), AS_XPN (op [i + 3])); /* multiply */ - WriteX (op[i], xop); /* write product */ - break; + case 011: /* XMPY 105211 (OP_AAXX) */ + i = 1; /* params start at op[1] */ + XMPY: /* enter here from .XMPY */ + if (intrq) { /* interrupt pending? */ + PC = err_PC; /* restart instruction */ + break; + } + O = x_mpy (&xop, AS_XPN (op [i + 1]), AS_XPN (op [i + 3])); /* multiply */ + WriteX (op[i], xop); /* write product */ + break; -case 012: /* XDIV 105212 (OP_AAXX) */ - i = 1; /* params start at op[1] */ -XDIV: /* enter here from .XDIV */ - if (intrq) { /* interrupt pending? */ - PC = err_PC; /* restart instruction */ - break; } - O = x_div (&xop, AS_XPN (op [i + 1]), AS_XPN (op [i + 3])); /* divide */ - WriteX (op[i], xop); /* write quotient */ - break; + case 012: /* XDIV 105212 (OP_AAXX) */ + i = 1; /* params start at op[1] */ + XDIV: /* enter here from .XDIV */ + if (intrq) { /* interrupt pending? */ + PC = err_PC; /* restart instruction */ + break; + } + O = x_div (&xop, AS_XPN (op [i + 1]), AS_XPN (op [i + 3])); /* divide */ + WriteX (op[i], xop); /* write quotient */ + break; -case 013: /* .XADD 105213 (OP_AXX) */ - i = 0; /* params start at op[0] */ - goto XADD; /* process as XADD */ + case 013: /* .XADD 105213 (OP_AXX) */ + i = 0; /* params start at op[0] */ + goto XADD; /* process as XADD */ -case 014: /* .XSUB 105214 (OP_AXX) */ - i = 0; /* params start at op[0] */ - goto XSUB; /* process as XSUB */ + case 014: /* .XSUB 105214 (OP_AXX) */ + i = 0; /* params start at op[0] */ + goto XSUB; /* process as XSUB */ -case 015: /* .XCOM 105215 (OP_A) */ - if (UNIT_CPU_TYPE != UNIT_TYPE_21MX) /* must be 21MX */ - return stop_inst; /* trap if not */ - xop = ReadX (op[0]); /* read operand */ - AR = x_com (&xop); /* neg and rtn exp adj */ - WriteX (op[0], xop); /* write result */ - break; + case 015: /* .XCOM 105215 (OP_A) */ + if (UNIT_CPU_TYPE != UNIT_TYPE_21MX) /* must be 21MX */ + return stop_inst; /* trap if not */ + xop = ReadX (op[0]); /* read operand */ + AR = x_com (&xop); /* neg and rtn exp adj */ + WriteX (op[0], xop); /* write result */ + break; -case 016: /* ..DCM 105216 (OP_A) */ - if (UNIT_CPU_TYPE != UNIT_TYPE_21MX) /* must be 21MX */ - return stop_inst; /* trap if not */ - if (intrq) { /* interrupt pending? */ - PC = err_PC; /* restart instruction */ - break; } - xop = ReadX (op[0]); /* read operand */ - O = x_dcm (&xop); /* negate */ - WriteX (op[0], xop); /* write result */ - break; + case 016: /* ..DCM 105216 (OP_A) */ + if (UNIT_CPU_TYPE != UNIT_TYPE_21MX) /* must be 21MX */ + return stop_inst; /* trap if not */ + if (intrq) { /* interrupt pending? */ + PC = err_PC; /* restart instruction */ + break; + } + xop = ReadX (op[0]); /* read operand */ + O = x_dcm (&xop); /* negate */ + WriteX (op[0], xop); /* write result */ + break; -case 017: /* DDINT 105217 (OP_AAX) */ - if (UNIT_CPU_TYPE != UNIT_TYPE_21MX) /* must be 21MX */ - return stop_inst; /* trap if not */ - if (intrq) { /* interrupt pending? */ - PC = err_PC; /* restart instruction */ - break; } - x_trun (&xop, AS_XPN (op [2])); /* truncate operand */ - WriteX (op[1], xop); /* write result */ - break; + case 017: /* DDINT 105217 (OP_AAX) */ + if (UNIT_CPU_TYPE != UNIT_TYPE_21MX) /* must be 21MX */ + return stop_inst; /* trap if not */ + if (intrq) { /* interrupt pending? */ + PC = err_PC; /* restart instruction */ + break; + } + x_trun (&xop, AS_XPN (op [2])); /* truncate operand */ + WriteX (op[1], xop); /* write result */ + break; #endif - + /* FFP module 2 */ -case 020: /* .XFER 105220 (OP_N) */ - if (UNIT_CPU_TYPE == UNIT_TYPE_2100) - PC = (PC + 1) & VAMASK; /* 2100 .XFER returns to P+2 */ -XFER: /* enter here from .DFER */ - sc = 3; /* set count for 3-wd xfer */ - goto CFER; /* do transfer */ + case 020: /* .XFER 105220 (OP_N) */ + if (UNIT_CPU_TYPE == UNIT_TYPE_2100) + PC = (PC + 1) & VAMASK; /* 2100 .XFER returns to P+2 */ + XFER: /* enter here from .DFER */ + sc = 3; /* set count for 3-wd xfer */ + goto CFER; /* do transfer */ -case 021: /* .GOTO 105221 (OP_AK) */ - if ((op[1] == 0) || (op[1] & SIGN)) /* index < 1? */ - op[1] = 1; /* reset min */ - sa = PC + op[1] - 1; /* point to jump target */ - if (sa >= op[0]) /* must be <= last target */ - sa = op[0] - 1; - da = ReadW (sa); /* get jump target */ - if (reason = resolve (da, &MA, intrq)) { /* resolve indirects */ - PC = err_PC; /* irq restarts instruction */ - break; } - mp_dms_jmp (MA); /* validate jump addr */ - PCQ_ENTRY; /* record last PC */ - PC = MA; /* jump */ - BR = op[0]; /* (for 2100 FFP compat) */ - break; + case 021: /* .GOTO 105221 (OP_AK) */ + if ((op[1] == 0) || (op[1] & SIGN)) /* index < 1? */ + op[1] = 1; /* reset min */ + sa = PC + op[1] - 1; /* point to jump target */ + if (sa >= op[0]) /* must be <= last target */ + sa = op[0] - 1; + da = ReadW (sa); /* get jump target */ + if (reason = resolve (da, &MA, intrq)) { /* resolve indirects */ + PC = err_PC; /* irq restarts instruction */ + break; + } + mp_dms_jmp (MA); /* validate jump addr */ + PCQ_ENTRY; /* record last PC */ + PC = MA; /* jump */ + BR = op[0]; /* (for 2100 FFP compat) */ + break; -case 022: /* ..MAP 105222 (OP_KKKK) */ - op[1] = op[1] - 1; /* decrement 1st subscr */ - if ((AR & 1) == 0) /* 2-dim access? */ - op[1] = op[1] + (op[2] - 1) * op[3]; /* compute element offset */ - else { /* 3-dim access */ - if (reason = get_ops (OP_KK, op2, intrq)) { /* get 1st, 2nd ranges */ - PC = err_PC; /* irq restarts instruction */ - break; } - op[1] = op[1] + ((op[3] - 1) * op2[1] + op[2] - 1) * op2[0]; } /* offset */ - AR = (op[0] + op[1] * BR) & DMASK; /* return element address */ - break; + case 022: /* ..MAP 105222 (OP_KKKK) */ + op[1] = op[1] - 1; /* decrement 1st subscr */ + if ((AR & 1) == 0) /* 2-dim access? */ + op[1] = op[1] + (op[2] - 1) * op[3]; /* compute element offset */ + else { /* 3-dim access */ + if (reason = get_ops (OP_KK, op2, intrq)) { /* get 1st, 2nd ranges */ + PC = err_PC; /* irq restarts instruction */ + break; + } + op[1] = op[1] + ((op[3] - 1) * op2[1] + op[2] - 1) * op2[0]; /* offset */ + } + AR = (op[0] + op[1] * BR) & DMASK; /* return element address */ + break; -case 023: /* .ENTR 105223 (OP_A) */ - MA = PC - 3; /* get addr of entry point */ -ENTR: /* enter here from .ENTP */ - da = op[0]; /* get addr of 1st formal */ - dc = MA - da; /* get count of formals */ - sa = ReadW (MA); /* get addr of return point */ - ra = ReadW (sa++); /* get rtn, ptr to 1st actual */ - WriteW (MA, ra); /* stuff rtn into caller's ent */ - sc = ra - sa; /* get count of actuals */ - if (sc > dc) sc = dc; /* use min (actuals, formals) */ - for (j = 0; j < sc; j++) { - MA = ReadW (sa++); /* get addr of actual */ - if (reason = resolve (MA, &MA, intrq)) { /* resolve indirect */ - PC = err_PC; /* irq restarts instruction */ - break; } - WriteW (da++, MA); } /* put addr into formal */ - AR = ra; /* return address */ - BR = da; /* addr of 1st unused formal */ - break; + case 023: /* .ENTR 105223 (OP_A) */ + MA = PC - 3; /* get addr of entry point */ + ENTR: /* enter here from .ENTP */ + da = op[0]; /* get addr of 1st formal */ + dc = MA - da; /* get count of formals */ + sa = ReadW (MA); /* get addr of return point */ + ra = ReadW (sa++); /* get rtn, ptr to 1st actual */ + WriteW (MA, ra); /* stuff rtn into caller's ent */ + sc = ra - sa; /* get count of actuals */ + if (sc > dc) sc = dc; /* use min (actuals, formals) */ + for (j = 0; j < sc; j++) { + MA = ReadW (sa++); /* get addr of actual */ + if (reason = resolve (MA, &MA, intrq)) { /* resolve indirect */ + PC = err_PC; /* irq restarts instruction */ + break; + } + WriteW (da++, MA); /* put addr into formal */ + } + AR = ra; /* return address */ + BR = da; /* addr of 1st unused formal */ + break; -case 024: /* .ENTP 105224 (OP_A) */ - MA = PC - 5; /* get addr of entry point */ - goto ENTR; + case 024: /* .ENTP 105224 (OP_A) */ + MA = PC - 5; /* get addr of entry point */ + goto ENTR; -case 025: /* .PWR2 105225 (OP_K) */ - if (UNIT_CPU_TYPE != UNIT_TYPE_21MX) /* must be 21MX */ - return stop_inst; /* trap if not */ - f_pwr2 (SEXT (op[0])); /* calc result into A/B */ - break; + case 025: /* .PWR2 105225 (OP_K) */ + if (UNIT_CPU_TYPE != UNIT_TYPE_21MX) /* must be 21MX */ + return stop_inst; /* trap if not */ + f_pwr2 (SEXT (op[0])); /* calc result into A/B */ + break; -case 026: /* .FLUN 105226 (OP_N) */ - if (UNIT_CPU_TYPE != UNIT_TYPE_21MX) /* must be 21MX */ - return stop_inst; /* trap if not */ - f_unpack (); /* unpack into A/B */ - break; + case 026: /* .FLUN 105226 (OP_N) */ + if (UNIT_CPU_TYPE != UNIT_TYPE_21MX) /* must be 21MX */ + return stop_inst; /* trap if not */ + f_unpack (); /* unpack into A/B */ + break; -case 027: /* $SETP 105227 (OP_K) */ - j = sa = AR; /* save initial value */ - sb = BR; /* save initial address */ - AR = 0; /* AR will return = 0 */ - BR = BR & VAMASK; /* addr must be direct */ - do { - WriteW (BR, j); /* write value to address */ - j = (j + 1) & DMASK; /* incr value */ - BR = (BR + 1) & VAMASK; /* incr address */ - op[0] = op[0] - 1; /* decr count */ - if (op[0] && intrq) { /* more and intr? */ - AR = sa; /* restore A */ - BR = sb; /* restore B */ - PC = err_PC; /* restart instruction */ - break; } } - while (op[0] != 0); /* loop until count exhausted */ - break; + case 027: /* $SETP 105227 (OP_K) */ + j = sa = AR; /* save initial value */ + sb = BR; /* save initial address */ + AR = 0; /* AR will return = 0 */ + BR = BR & VAMASK; /* addr must be direct */ + do { + WriteW (BR, j); /* write value to address */ + j = (j + 1) & DMASK; /* incr value */ + BR = (BR + 1) & VAMASK; /* incr address */ + op[0] = op[0] - 1; /* decr count */ + if (op[0] && intrq) { /* more and intr? */ + AR = sa; /* restore A */ + BR = sb; /* restore B */ + PC = err_PC; /* restart instruction */ + break; + } + } + while (op[0] != 0); /* loop until count exhausted */ + break; -case 030: /* .PACK 105230 (OP_C) */ - if (UNIT_CPU_TYPE != UNIT_TYPE_21MX) /* must be 21MX */ - return stop_inst; /* trap if not */ - O = f_pack (SEXT (op[0])); /* calc A/B and overflow */ - break; + case 030: /* .PACK 105230 (OP_C) */ + if (UNIT_CPU_TYPE != UNIT_TYPE_21MX) /* must be 21MX */ + return stop_inst; /* trap if not */ + O = f_pack (SEXT (op[0])); /* calc A/B and overflow */ + break; -case 031: /* .CFER 105231 (OP_AA) */ - if (UNIT_CPU_MODEL != UNIT_21MX_E) /* must be 21MX E-series */ - return stop_inst; /* trap if not */ - BR = op[0]; /* get destination address */ - AR = op[1]; /* get source address */ - sc = 4; /* set for 4-wd xfer */ -CFER: /* enter here from .XFER */ - for (j = 0; j < sc; j++) { /* xfer loop */ - WriteW (BR, ReadW (AR)); /* transfer word */ - AR = (AR + 1) & VAMASK; /* bump source addr */ - BR = (BR + 1) & VAMASK; } /* bump destination addr */ - E = 0; /* routine clears E */ - if (UNIT_CPU_TYPE == UNIT_TYPE_2100) { /* 2100 (and .DFER/.XFER)? */ - AR = (AR + 1) & VAMASK; /* 2100 FFP returns X+4, Y+4 */ - BR = (BR + 1) & VAMASK; } - break; + case 031: /* .CFER 105231 (OP_AA) */ + if (UNIT_CPU_MODEL != UNIT_21MX_E) /* must be 21MX E-series */ + return stop_inst; /* trap if not */ + BR = op[0]; /* get destination address */ + AR = op[1]; /* get source address */ + sc = 4; /* set for 4-wd xfer */ + CFER: /* enter here from .XFER */ + for (j = 0; j < sc; j++) { /* xfer loop */ + WriteW (BR, ReadW (AR)); /* transfer word */ + AR = (AR + 1) & VAMASK; /* bump source addr */ + BR = (BR + 1) & VAMASK; /* bump destination addr */ + } + E = 0; /* routine clears E */ + if (UNIT_CPU_TYPE == UNIT_TYPE_2100) { /* 2100 (and .DFER/.XFER)? */ + AR = (AR + 1) & VAMASK; /* 2100 FFP returns X+4, Y+4 */ + BR = (BR + 1) & VAMASK; + } + break; -default: /* others undefined */ - reason = stop_inst; } + default: /* others undefined */ + reason = stop_inst; + } return reason; } - + /* 2000 I/O Processor The IOP accelerates certain operations of the HP 2000 Time-Share BASIC system @@ -922,28 +950,28 @@ return reason; The routines are mapped to instruction codes as follows: - Instr. 2100 21MX-M/E Description + Instr. 2100 21MX-M/E Description ------ ---------- ---------- -------------------------------------------- SAI 105060-117 101400-037 Store A indexed by B (+/- offset in IR<4:0>) LAI 105020-057 105400-037 Load A indexed by B (+/- offset in IR<4:0>) - CRC 105150 105460 Generate CRC - REST 105340 105461 Restore registers from stack - READF 105220 105462 Read F register (stack pointer) - INS -- 105463 Initialize F register (stack pointer) - ENQ 105240 105464 Enqueue - PENQ 105257 105465 Priority enqueue - DEQ 105260 105466 Dequeue - TRSLT 105160 105467 Translate character - ILIST 105000 105470 Indirect address list (similar to $SETP) - PRFEI 105222 105471 Power fail exit with I/O - PRFEX 105223 105472 Power fail exit - PRFIO 105221 105473 Power fail I/O - SAVE 105362 105474 Save registers to stack + CRC 105150 105460 Generate CRC + REST 105340 105461 Restore registers from stack + READF 105220 105462 Read F register (stack pointer) + INS -- 105463 Initialize F register (stack pointer) + ENQ 105240 105464 Enqueue + PENQ 105257 105465 Priority enqueue + DEQ 105260 105466 Dequeue + TRSLT 105160 105467 Translate character + ILIST 105000 105470 Indirect address list (similar to $SETP) + PRFEI 105222 105471 Power fail exit with I/O + PRFEX 105223 105472 Power fail exit + PRFIO 105221 105473 Power fail I/O + SAVE 105362 105474 Save registers to stack - MBYTE 105120 105765 Move bytes (MBT) - MWORD 105200 105777 Move words (MVW) - SBYTE 105300 105764 Store byte (SBT) - LBYTE 105320 105763 Load byte (LBT) + MBYTE 105120 105765 Move bytes (MBT) + MWORD 105200 105777 Move words (MVW) + SBYTE 105300 105764 Store byte (SBT) + LBYTE 105320 105763 Load byte (LBT) The INS instruction was not required in the 2100 implementation because the stack pointer was actually the memory protect fence register and so could be @@ -953,14 +981,15 @@ return reason; Additional reference: - HP 2000 Computer System Sources and Listings Documentation - (22687-90020, undated), section 3, pages 2-74 through 2-91. + (22687-90020, undated), section 3, pages 2-74 through 2-91. */ static const OP_PAT op_iop[16] = { - OP_V, OP_N, OP_N, OP_N, /* CRC RESTR READF INS */ - OP_N, OP_N, OP_N, OP_V, /* ENQ PENQ DEQ TRSLT */ - OP_AC, OP_CVA, OP_A, OP_CV, /* ILIST PRFEI PRFEX PRFIO */ - OP_N, OP_N, OP_N, OP_N }; /* SAVE --- --- --- */ + OP_V, OP_N, OP_N, OP_N, /* CRC RESTR READF INS */ + OP_N, OP_N, OP_N, OP_V, /* ENQ PENQ DEQ TRSLT */ + OP_AC, OP_CVA, OP_A, OP_CV, /* ILIST PRFEI PRFEX PRFIO */ + OP_N, OP_N, OP_N, OP_N /* SAVE --- --- --- */ + }; static t_stat cpu_iop (uint32 IR, uint32 intrq) { @@ -969,143 +998,150 @@ OPS op; uint32 entry; uint32 hp, tp, i, t, wc, MA; -if ((cpu_unit.flags & UNIT_IOP) == 0) /* IOP option installed? */ - return stop_inst; +if ((cpu_unit.flags & UNIT_IOP) == 0) /* IOP option installed? */ + return stop_inst; -entry = IR & 077; /* mask to entry point */ +entry = IR & 077; /* mask to entry point */ -if (entry <= 037) { /* LAI/SAI 10x400-437 */ - MA = ((entry - 020) + BR) & VAMASK; /* +/- offset */ - if (IR & I_AB) AR = ReadW (MA); /* AB = 1 -> LAI */ - else WriteW (MA, AR); /* AB = 0 -> SAI */ - return reason; } -else if (entry <= 057) /* IR = 10x440-457? */ - return stop_inst; /* not part of IOP */ +if (entry <= 037) { /* LAI/SAI 10x400-437 */ + MA = ((entry - 020) + BR) & VAMASK; /* +/- offset */ + if (IR & I_AB) AR = ReadW (MA); /* AB = 1 -> LAI */ + else WriteW (MA, AR); /* AB = 0 -> SAI */ + return reason; + } +else if (entry <= 057) /* IR = 10x440-457? */ + return stop_inst; /* not part of IOP */ -entry = entry - 060; /* offset 10x460-477 */ +entry = entry - 060; /* offset 10x460-477 */ -if (op_iop[entry] != OP_N) - if (reason = get_ops (op_iop[entry], op, intrq))/* get instruction operands */ - return reason; +if (op_iop[entry] != OP_N) { + if (reason = get_ops (op_iop[entry], op, intrq)) /* get instruction operands */ + return reason; + } -switch (entry) { /* decode IR<5:0> */ +switch (entry) { /* decode IR<5:0> */ -case 000: /* CRC 105460 (OP_V) */ - t = ReadW (op[0]) ^ (AR & 0377); /* xor prev CRC and char */ - 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 (op[0], t); /* rewrite CRC */ - break; + case 000: /* CRC 105460 (OP_V) */ + t = ReadW (op[0]) ^ (AR & 0377); /* xor prev CRC and char */ + 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 (op[0], t); /* rewrite CRC */ + break; -case 001: /* RESTR 105461 (OP_N) */ - iop_sp = (iop_sp - 1) & VAMASK; /* decr stack ptr */ - t = ReadW (iop_sp); /* get E and O */ - O = ((t >> 1) ^ 1) & 1; /* restore O */ - E = t & 1; /* restore E */ - iop_sp = (iop_sp - 1) & VAMASK; /* decr sp */ - BR = ReadW (iop_sp); /* restore B */ - iop_sp = (iop_sp - 1) & VAMASK; /* decr sp */ - AR = ReadW (iop_sp); /* restore A */ - if (UNIT_CPU_MODEL == UNIT_2100) - mp_fence = iop_sp; /* 2100 keeps sp in MP FR */ - break; + case 001: /* RESTR 105461 (OP_N) */ + iop_sp = (iop_sp - 1) & VAMASK; /* decr stack ptr */ + t = ReadW (iop_sp); /* get E and O */ + O = ((t >> 1) ^ 1) & 1; /* restore O */ + E = t & 1; /* restore E */ + iop_sp = (iop_sp - 1) & VAMASK; /* decr sp */ + BR = ReadW (iop_sp); /* restore B */ + iop_sp = (iop_sp - 1) & VAMASK; /* decr sp */ + AR = ReadW (iop_sp); /* restore A */ + if (UNIT_CPU_MODEL == UNIT_2100) + mp_fence = iop_sp; /* 2100 keeps sp in MP FR */ + break; -case 002: /* READF 105462 (OP_N) */ - AR = iop_sp; /* copy stk ptr */ - break; + case 002: /* READF 105462 (OP_N) */ + AR = iop_sp; /* copy stk ptr */ + break; -case 003: /* INS 105463 (OP_N) */ - iop_sp = AR; /* init stk ptr */ - break; + case 003: /* INS 105463 (OP_N) */ + iop_sp = AR; /* init stk ptr */ + break; -case 004: /* ENQ 105464 (OP_N) */ - 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 004: /* ENQ 105464 (OP_N) */ + 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 005: /* PENQ 105465 (OP_N) */ - 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 005: /* PENQ 105465 (OP_N) */ + 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 006: /* DEQ 105466 (OP_N) */ - 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 006: /* DEQ 105466 (OP_N) */ + 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 007: /* TRSLT 105467 (OP_V) */ - wc = ReadW (op[0]); /* get count */ - 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 */ - if (wc && intrq) { /* more and intr? */ - WriteW (op[0], wc); /* save count */ - PC = err_PC; /* stop for now */ - break; } } - break; + case 007: /* TRSLT 105467 (OP_V) */ + wc = ReadW (op[0]); /* get count */ + 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 */ + if (wc && intrq) { /* more and intr? */ + WriteW (op[0], wc); /* save count */ + PC = err_PC; /* stop for now */ + break; + } + } + break; -case 010: /* ILIST 105470 (OP_AC) */ - do { /* for count */ - WriteW (op[0], AR); /* write AR to mem */ - AR = (AR + 1) & DMASK; /* incr AR */ - op[0] = (op[0] + 1) & VAMASK; /* incr MA */ - op[1] = (op[1] - 1) & DMASK; } /* decr count */ - while (op[1] != 0); - break; + case 010: /* ILIST 105470 (OP_AC) */ + do { /* for count */ + WriteW (op[0], AR); /* write AR to mem */ + AR = (AR + 1) & DMASK; /* incr AR */ + op[0] = (op[0] + 1) & VAMASK; /* incr MA */ + op[1] = (op[1] - 1) & DMASK; /* decr count */ + } + while (op[1] != 0); + break; -case 011: /* PRFEI 105471 (OP_CVA) */ - WriteW (op[1], 1); /* set flag */ - reason = iogrp (op[0], 0); /* execute I/O instr */ - op[0] = op[2]; /* set rtn and fall through */ + case 011: /* PRFEI 105471 (OP_CVA) */ + WriteW (op[1], 1); /* set flag */ + reason = iogrp (op[0], 0); /* execute I/O instr */ + op[0] = op[2]; /* set rtn and fall through */ -case 012: /* PRFEX 105472 (OP_A) */ - PCQ_ENTRY; - PC = ReadW (op[0]) & VAMASK; /* jump indirect */ - WriteW (op[0], 0); /* clear exit */ - break; + case 012: /* PRFEX 105472 (OP_A) */ + PCQ_ENTRY; + PC = ReadW (op[0]) & VAMASK; /* jump indirect */ + WriteW (op[0], 0); /* clear exit */ + break; -case 013: /* PRFIO 105473 (OP_CV) */ - WriteW (op[1], 1); /* set flag */ - reason = iogrp (op[0], 0); /* execute instr */ - break; + case 013: /* PRFIO 105473 (OP_CV) */ + WriteW (op[1], 1); /* set flag */ + reason = iogrp (op[0], 0); /* execute instr */ + break; -case 014: /* SAVE 105474 (OP_N) */ - WriteW (iop_sp, AR); /* save A */ - iop_sp = (iop_sp + 1) & VAMASK; /* incr stack ptr */ - WriteW (iop_sp, BR); /* save B */ - iop_sp = (iop_sp + 1) & VAMASK; /* incr stack ptr */ - t = ((O ^ 1) << 1) | E; /* merge E and O */ - WriteW (iop_sp, t); /* save E and O */ - iop_sp = (iop_sp + 1) & VAMASK; /* incr stack ptr */ - if (UNIT_CPU_TYPE == UNIT_TYPE_2100) - mp_fence = iop_sp; /* 2100 keeps sp in MP FR */ - break; + case 014: /* SAVE 105474 (OP_N) */ + WriteW (iop_sp, AR); /* save A */ + iop_sp = (iop_sp + 1) & VAMASK; /* incr stack ptr */ + WriteW (iop_sp, BR); /* save B */ + iop_sp = (iop_sp + 1) & VAMASK; /* incr stack ptr */ + t = ((O ^ 1) << 1) | E; /* merge E and O */ + WriteW (iop_sp, t); /* save E and O */ + iop_sp = (iop_sp + 1) & VAMASK; /* incr stack ptr */ + if (UNIT_CPU_TYPE == UNIT_TYPE_2100) + mp_fence = iop_sp; /* 2100 keeps sp in MP FR */ + break; -default: /* instruction undefined */ - return stop_inst; - } + default: /* instruction undefined */ + return stop_inst; + } return reason; } - + /* Dynamic Mapping System The 21MX Dynamic Mapping System (DMS) consisted of the 12731A Memory @@ -1127,23 +1163,23 @@ return reason; Instr. 21MX-M 21MX-E/F Instr. 21MX-M 21MX-E/F ------ ------ -------- ------ ------ -------- - 10x700 [xmm] [xmm] 10x720 XMM XMM - 10x701 [nop] [test] 10x721 XMS XMS - 10x702 MBI MBI 10x722 XM* XM* - 10x703 MBF MBF 10x723 [nop] [nop] - 10x704 MBW MBW 10x724 XL* XL* - 10x705 MWI MWI 10x725 XS* XS* - 10x706 MWF MWF 10x726 XC* XC* - 10x707 MWW MWW 10x727 LF* LF* - 10x710 SY* SY* 10x730 RS* RS* + 10x700 [xmm] [xmm] 10x720 XMM XMM + 10x701 [nop] [test] 10x721 XMS XMS + 10x702 MBI MBI 10x722 XM* XM* + 10x703 MBF MBF 10x723 [nop] [nop] + 10x704 MBW MBW 10x724 XL* XL* + 10x705 MWI MWI 10x725 XS* XS* + 10x706 MWF MWF 10x726 XC* XC* + 10x707 MWW MWW 10x727 LF* LF* + 10x710 SY* SY* 10x730 RS* RS* - 10x711 US* US* 10x731 RV* RV* - 10x712 PA* PA* 10x732 DJP DJP - 10x713 PB* PB* 10x733 DJS DJS - 10x714 SSM SSM 10x734 SJP SJP - 10x715 JRS JRS 10x735 SJS SJS - 10x716 [nop] [nop] 10x736 UJP UJP - 10x717 [nop] [nop] 10x737 UJS UJS + 10x711 US* US* 10x731 RV* RV* + 10x712 PA* PA* 10x732 DJP DJP + 10x713 PB* PB* 10x733 DJS DJS + 10x714 SSM SSM 10x734 SJP SJP + 10x715 JRS JRS 10x735 SJS SJS + 10x716 [nop] [nop] 10x736 UJP UJP + 10x717 [nop] [nop] 10x737 UJS UJS Instructions that use IR bit 9 to select the A or B register are designated with a * above (e.g., 101710 is SYA, and 105710 is SYB). For those that do @@ -1154,25 +1190,26 @@ return reason; Notes: 1. Instruction code 10x700 will execute the XMM instruction, although - 10x720 is the documented instruction value. + 10x720 is the documented instruction value. 2. The DMS privilege violation rules are: - - load map and CTL5 set (XMM, XMS, XM*, SY*, US*, PA*, PB*) - - load state or fence and UMAP set (JRS, DJP, DJS, SJP, SJS, UJP, UJS, LF*) + - load map and CTL5 set (XMM, XMS, XM*, SY*, US*, PA*, PB*) + - load state or fence and UMAP set (JRS, DJP, DJS, SJP, SJS, UJP, UJS, LF*) 3. The 21MX manual is incorrect in stating that M*I, M*W, XS* are - privileged. + privileged. */ static const OP_PAT op_dms[32] = { - OP_N, OP_N, OP_N, OP_N, /* xmm test MBI MBF */ - OP_N, OP_N, OP_N, OP_N, /* MBW MWI MWF MWW */ - OP_N, OP_N, OP_N, OP_N, /* SYA/B USA/B PAA/B PBA/B */ - OP_A, OP_KA, OP_N, OP_N, /* SSM JRS nop nop */ - OP_N, OP_N, OP_N, OP_N, /* XMM XMS XMA/B nop */ - OP_A, OP_A, OP_A, OP_N, /* XLA/B XSA/B XCA/B LFA/B */ - OP_N, OP_N, OP_A, OP_A, /* RSA/B RVA/B DJP DJS */ - OP_A, OP_A, OP_A, OP_A }; /* SJP SJS UJP UJS */ + OP_N, OP_N, OP_N, OP_N, /* xmm test MBI MBF */ + OP_N, OP_N, OP_N, OP_N, /* MBW MWI MWF MWW */ + OP_N, OP_N, OP_N, OP_N, /* SYA/B USA/B PAA/B PBA/B */ + OP_A, OP_KA, OP_N, OP_N, /* SSM JRS nop nop */ + OP_N, OP_N, OP_N, OP_N, /* XMM XMS XMA/B nop */ + OP_A, OP_A, OP_A, OP_N, /* XLA/B XSA/B XCA/B LFA/B */ + OP_N, OP_N, OP_A, OP_A, /* RSA/B RVA/B DJP DJS */ + OP_A, OP_A, OP_A, OP_A /* SJP SJS UJP UJS */ + }; static t_stat cpu_dms (uint32 IR, uint32 intrq) { @@ -1181,280 +1218,306 @@ OPS op; uint32 entry, absel; uint32 i, t, mapi, mapj; -if ((cpu_unit.flags & UNIT_DMS) == 0) /* DMS option installed? */ - return stop_inst; +if ((cpu_unit.flags & UNIT_DMS) == 0) /* DMS option installed? */ + return stop_inst; -absel = (IR & I_AB)? 1: 0; /* get A/B select */ -entry = IR & 037; /* mask to entry point */ +absel = (IR & I_AB)? 1: 0; /* get A/B select */ +entry = IR & 037; /* mask to entry point */ -if (op_dms[entry] != OP_N) - if (reason = get_ops (op_dms[entry], op, intrq))/* get instruction operands */ - return reason; +if (op_dms[entry] != OP_N) { + if (reason = get_ops (op_dms[entry], op, intrq)) /* get instruction operands */ + return reason; + } -switch (entry) { /* decode IR<3:0> */ +switch (entry) { /* decode IR<3:0> */ /* DMS module 1 */ -case 000: /* [undefined] 105700 (OP_N) */ - goto XMM; /* decodes as XMM */ + case 000: /* [undefined] 105700 (OP_N) */ + goto XMM; /* decodes as XMM */ -case 001: /* [self test] 105701 (OP_N) */ - ABREG[absel] = ABREG[absel] ^ DMASK; /* CMA or CMB */ - break; + case 001: /* [self test] 105701 (OP_N) */ + ABREG[absel] = ABREG[absel] ^ DMASK; /* CMA or CMB */ + break; -case 002: /* MBI 105702 (OP_N) */ - 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 002: /* MBI 105702 (OP_N) */ + 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 003: /* MBF 105703 (OP_N) */ - 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 003: /* MBF 105703 (OP_N) */ + 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 004: /* MBW 105704 (OP_N) */ - 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 004: /* MBW 105704 (OP_N) */ + 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 005: /* MWI 105705 (OP_N) */ - 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 005: /* MWI 105705 (OP_N) */ + 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 006: /* MWF 105706 (OP_N) */ - 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 006: /* MWF 105706 (OP_N) */ + 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 007: /* MWW 105707 (OP_N) */ - 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; + case 007: /* MWW 105707 (OP_N) */ + 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; -case 010: /* SYA, SYB 10x710 (OP_N) */ -case 011: /* USA, USB 10x711 (OP_N) */ -case 012: /* PAA, PAB 10x712 (OP_N) */ -case 013: /* PBA, PBB 10x713 (OP_N) */ - 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 010: /* SYA, SYB 10x710 (OP_N) */ + case 011: /* USA, USB 10x711 (OP_N) */ + case 012: /* PAA, PAB 10x712 (OP_N) */ + case 013: /* PBA, PBB 10x713 (OP_N) */ + 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 014: /* SSM 105714 (OP_A) */ - WriteW (op[0], dms_upd_sr ()); /* store stat */ - break; + case 014: /* SSM 105714 (OP_A) */ + WriteW (op[0], dms_upd_sr ()); /* store stat */ + break; + + case 015: /* JRS 105715 (OP_KA) */ + if (dms_ump) dms_viol (err_PC, MVI_PRV); /* priv viol if prot */ + dms_enb = 0; /* assume off */ + dms_ump = SMAP; + if (op[0] & 0100000) { /* set enable? */ + dms_enb = 1; + if (op[0] & 0040000) dms_ump = UMAP; /* set/clr usr */ + } + mp_dms_jmp (op[1]); /* mpck jmp target */ + PCQ_ENTRY; /* save old PC */ + PC = op[1]; /* jump */ + ion_defer = 1; /* defer intr */ + break; -case 015: /* JRS 105715 (OP_KA) */ - if (dms_ump) dms_viol (err_PC, MVI_PRV); /* priv viol if prot */ - dms_enb = 0; /* assume off */ - dms_ump = SMAP; - if (op[0] & 0100000) { /* set enable? */ - dms_enb = 1; - if (op[0] & 0040000) dms_ump = UMAP; } /* set/clr usr */ - mp_dms_jmp (op[1]); /* mpck jmp target */ - PCQ_ENTRY; /* save old PC */ - PC = op[1]; /* jump */ - ion_defer = 1; /* defer intr */ - break; - /* DMS module 2 */ -case 020: /* XMM 105720 (OP_N) */ -XMM: - 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 viol if prot */ - 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 & 017) == 017)) { /* intr, grp of 16? */ - PC = err_PC; /* stop for now */ - break; } } - break; + case 020: /* XMM 105720 (OP_N) */ + XMM: + 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 viol if prot */ + 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 & 017) == 017)) { /* intr, grp of 16? */ + PC = err_PC; /* stop for now */ + break; + } + } + break; -case 021: /* XMS 105721 (OP_N) */ - if ((XR & SIGN) || (XR == 0)) break; /* nop? */ - dms_viol (err_PC, MVI_PRV); /* priv viol if prot */ - 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 & 017) == 017)) { /* intr, grp of 16? */ - PC = err_PC; - break; } } - break; + case 021: /* XMS 105721 (OP_N) */ + if ((XR & SIGN) || (XR == 0)) break; /* nop? */ + dms_viol (err_PC, MVI_PRV); /* priv viol if prot */ + 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 & 017) == 017)) { /* intr, grp of 16? */ + PC = err_PC; + break; + } + } + break; -case 022: /* XMA, XMB 10x722 (OP_N) */ - dms_viol (err_PC, MVI_PRV); /* priv viol if prot */ - 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 022: /* XMA, XMB 10x722 (OP_N) */ + dms_viol (err_PC, MVI_PRV); /* priv viol if prot */ + 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 024: /* XLA, XLB 10x724 (OP_A) */ - ABREG[absel] = ReadWA (op[0]); /* load alt */ - break; + case 024: /* XLA, XLB 10x724 (OP_A) */ + ABREG[absel] = ReadWA (op[0]); /* load alt */ + break; -case 025: /* XSA, XSB 10x725 (OP_A) */ - WriteWA (op[0], ABREG[absel]); /* store alt */ - break; + case 025: /* XSA, XSB 10x725 (OP_A) */ + WriteWA (op[0], ABREG[absel]); /* store alt */ + break; -case 026: /* XCA, XCB 10x726 (OP_A) */ - if (ABREG[absel] != ReadWA (op[0])) /* compare alt */ - PC = (PC + 1) & VAMASK; - break; + case 026: /* XCA, XCB 10x726 (OP_A) */ + if (ABREG[absel] != ReadWA (op[0])) /* compare alt */ + PC = (PC + 1) & VAMASK; + break; -case 027: /* LFA, LFB 10x727 (OP_N) */ - if (dms_ump) dms_viol (err_PC, MVI_PRV); /* priv viol if prot */ - dms_sr = (dms_sr & ~(MST_FLT | MST_FENCE)) | - (ABREG[absel] & (MST_FLT | MST_FENCE)); - break; + case 027: /* LFA, LFB 10x727 (OP_N) */ + if (dms_ump) dms_viol (err_PC, MVI_PRV); /* priv viol if prot */ + dms_sr = (dms_sr & ~(MST_FLT | MST_FENCE)) | + (ABREG[absel] & (MST_FLT | MST_FENCE)); + break; -case 030: /* RSA, RSB 10x730 (OP_N) */ - ABREG[absel] = dms_upd_sr (); /* save stat */ - break; + case 030: /* RSA, RSB 10x730 (OP_N) */ + ABREG[absel] = dms_upd_sr (); /* save stat */ + break; -case 031: /* RVA, RVB 10x731 (OP_N) */ - ABREG[absel] = dms_vr; /* save viol */ - break; + case 031: /* RVA, RVB 10x731 (OP_N) */ + ABREG[absel] = dms_vr; /* save viol */ + break; -case 032: /* DJP 105732 (OP_A) */ - if (dms_ump) dms_viol (err_PC, MVI_PRV); /* priv viol if prot */ - mp_dms_jmp (op[0]); /* validate jump addr */ - PCQ_ENTRY; /* save curr PC */ - PC = op[0]; /* new PC */ - dms_enb = 0; /* disable map */ - dms_ump = SMAP; - ion_defer = 1; - break; + case 032: /* DJP 105732 (OP_A) */ + if (dms_ump) dms_viol (err_PC, MVI_PRV); /* priv viol if prot */ + mp_dms_jmp (op[0]); /* validate jump addr */ + PCQ_ENTRY; /* save curr PC */ + PC = op[0]; /* new PC */ + dms_enb = 0; /* disable map */ + dms_ump = SMAP; + ion_defer = 1; + break; -case 033: /* DJS 105733 (OP_A) */ - if (dms_ump) dms_viol (err_PC, MVI_PRV); /* priv viol if prot */ - WriteW (op[0], PC); /* store ret addr */ - PCQ_ENTRY; /* save curr PC */ - PC = (op[0] + 1) & VAMASK; /* new PC */ - dms_enb = 0; /* disable map */ - dms_ump = SMAP; - ion_defer = 1; /* defer intr */ - break; + case 033: /* DJS 105733 (OP_A) */ + if (dms_ump) dms_viol (err_PC, MVI_PRV); /* priv viol if prot */ + WriteW (op[0], PC); /* store ret addr */ + PCQ_ENTRY; /* save curr PC */ + PC = (op[0] + 1) & VAMASK; /* new PC */ + dms_enb = 0; /* disable map */ + dms_ump = SMAP; + ion_defer = 1; /* defer intr */ + break; -case 034: /* SJP 105734 (OP_A) */ - if (dms_ump) dms_viol (err_PC, MVI_PRV); /* priv viol if prot */ - mp_dms_jmp (op[0]); /* validate jump addr */ - PCQ_ENTRY; /* save curr PC */ - PC = op[0]; /* jump */ - dms_enb = 1; /* enable system */ - dms_ump = SMAP; - ion_defer = 1; /* defer intr */ - break; + case 034: /* SJP 105734 (OP_A) */ + if (dms_ump) dms_viol (err_PC, MVI_PRV); /* priv viol if prot */ + mp_dms_jmp (op[0]); /* validate jump addr */ + PCQ_ENTRY; /* save curr PC */ + PC = op[0]; /* jump */ + dms_enb = 1; /* enable system */ + dms_ump = SMAP; + ion_defer = 1; /* defer intr */ + break; -case 035: /* SJS 105735 (OP_A) */ - if (dms_ump) dms_viol (err_PC, MVI_PRV); /* priv viol if prot */ - t = PC; /* save retn addr */ - PCQ_ENTRY; /* save curr PC */ - PC = (op[0] + 1) & VAMASK; /* new PC */ - dms_enb = 1; /* enable system */ - dms_ump = SMAP; - WriteW (op[0], t); /* store ret addr */ - ion_defer = 1; /* defer intr */ - break; + case 035: /* SJS 105735 (OP_A) */ + if (dms_ump) dms_viol (err_PC, MVI_PRV); /* priv viol if prot */ + t = PC; /* save retn addr */ + PCQ_ENTRY; /* save curr PC */ + PC = (op[0] + 1) & VAMASK; /* new PC */ + dms_enb = 1; /* enable system */ + dms_ump = SMAP; + WriteW (op[0], t); /* store ret addr */ + ion_defer = 1; /* defer intr */ + break; -case 036: /* UJP 105736 (OP_A) */ - if (dms_ump) dms_viol (err_PC, MVI_PRV); /* priv viol if prot */ - mp_dms_jmp (op[0]); /* validate jump addr */ - PCQ_ENTRY; /* save curr PC */ - PC = op[0]; /* jump */ - dms_enb = 1; /* enable user */ - dms_ump = UMAP; - ion_defer = 1; /* defer intr */ - break; + case 036: /* UJP 105736 (OP_A) */ + if (dms_ump) dms_viol (err_PC, MVI_PRV); /* priv viol if prot */ + mp_dms_jmp (op[0]); /* validate jump addr */ + PCQ_ENTRY; /* save curr PC */ + PC = op[0]; /* jump */ + dms_enb = 1; /* enable user */ + dms_ump = UMAP; + ion_defer = 1; /* defer intr */ + break; -case 037: /* UJS 105737 (OP_A) */ - if (dms_ump) dms_viol (err_PC, MVI_PRV); /* priv viol if prot */ - t = PC; /* save retn addr */ - PCQ_ENTRY; /* save curr PC */ - PC = (op[0] + 1) & VAMASK; /* new PC */ - dms_enb = 1; /* enable user */ - dms_ump = UMAP; - WriteW (op[0], t); /* store ret addr */ - ion_defer = 1; /* defer intr */ - break; + case 037: /* UJS 105737 (OP_A) */ + if (dms_ump) dms_viol (err_PC, MVI_PRV); /* priv viol if prot */ + t = PC; /* save retn addr */ + PCQ_ENTRY; /* save curr PC */ + PC = (op[0] + 1) & VAMASK; /* new PC */ + dms_enb = 1; /* enable user */ + dms_ump = UMAP; + WriteW (op[0], t); /* store ret addr */ + ion_defer = 1; /* defer intr */ + break; -default: /* others NOP */ - break; } + default: /* others NOP */ + break; + } return reason; } - + /* Extended Instruction Group The Extended Instruction Group (EIG) adds 32 index and 10 bit/byte/word @@ -1471,23 +1534,23 @@ return reason; Instr. 21MX-M/E/F Instr. 21MX-M/E/F ------ ---------- ------ ---------- - 10x740 S*X 10x760 ISX - 10x741 C*X 10x761 DSX - 10x742 L*X 10x762 JLY - 10x743 STX 10x763 LBT - 10x744 CX* 10x764 SBT - 10x745 LDX 10x765 MBT - 10x746 ADX 10x766 CBT - 10x747 X*X 10x767 SFB + 10x740 S*X 10x760 ISX + 10x741 C*X 10x761 DSX + 10x742 L*X 10x762 JLY + 10x743 STX 10x763 LBT + 10x744 CX* 10x764 SBT + 10x745 LDX 10x765 MBT + 10x746 ADX 10x766 CBT + 10x747 X*X 10x767 SFB - 10x750 S*Y 10x770 ISY - 10x751 C*Y 10x771 DSY - 10x752 L*Y 10x772 JPY - 10x753 STY 10x773 SBS - 10x754 CY* 10x774 CBS - 10x755 LDY 10x775 TBS - 10x756 ADY 10x776 CMW - 10x757 X*Y 10x777 MVW + 10x750 S*Y 10x770 ISY + 10x751 C*Y 10x771 DSY + 10x752 L*Y 10x772 JPY + 10x753 STY 10x773 SBS + 10x754 CY* 10x774 CBS + 10x755 LDY 10x775 TBS + 10x756 ADY 10x776 CMW + 10x757 X*Y 10x777 MVW Instructions that use IR bit 9 to select the A or B register are designated with a * above (e.g., 101740 is SAX, and 105740 is SBX). For those that do @@ -1498,19 +1561,20 @@ return reason; Notes: 1. The LBT, SBT, MBT, and MVW instructions are used as part of the 2100 IOP - implementation. When so called, the MBT and MVW instructions have the - additional restriction that the count must be positive. + implementation. When so called, the MBT and MVW instructions have the + additional restriction that the count must be positive. */ static const OP_PAT op_eig[32] = { - OP_A, OP_N, OP_A, OP_A, /* S*X C*X L*X STX */ - OP_N, OP_K, OP_K, OP_N, /* CX* LDX ADX X*X */ - OP_A, OP_N, OP_A, OP_A, /* S*Y C*Y L*Y STY */ - OP_N, OP_K, OP_K, OP_N, /* CY* LDY ADY X*Y */ - OP_N, OP_N, OP_A, OP_N, /* ISX DSX JLY LBT */ - OP_N, OP_KV, OP_KV, OP_N, /* SBT MBT CBT SFB */ - OP_N, OP_N, OP_C, OP_KA, /* ISY DSY JPY SBS */ - OP_KA, OP_KK, OP_KV, OP_KV }; /* CBS TBS CMW MVW */ + OP_A, OP_N, OP_A, OP_A, /* S*X C*X L*X STX */ + OP_N, OP_K, OP_K, OP_N, /* CX* LDX ADX X*X */ + OP_A, OP_N, OP_A, OP_A, /* S*Y C*Y L*Y STY */ + OP_N, OP_K, OP_K, OP_N, /* CY* LDY ADY X*Y */ + OP_N, OP_N, OP_A, OP_N, /* ISX DSX JLY LBT */ + OP_N, OP_KV, OP_KV, OP_N, /* SBT MBT CBT SFB */ + OP_N, OP_N, OP_C, OP_KA, /* ISY DSY JPY SBS */ + OP_KA, OP_KK, OP_KV, OP_KV /* CBS TBS CMW MVW */ + }; static t_stat cpu_eig (uint32 IR, uint32 intrq) { @@ -1520,255 +1584,270 @@ uint32 entry, absel; uint32 t, v1, v2, wc; int32 sop1, sop2; -absel = (IR & I_AB)? 1: 0; /* get A/B select */ -entry = IR & 037; /* mask to entry point */ +absel = (IR & I_AB)? 1: 0; /* get A/B select */ +entry = IR & 037; /* mask to entry point */ -if (op_eig[entry] != OP_N) - if (reason = get_ops (op_eig[entry], op, intrq))/* get instruction operands */ - return reason; +if (op_eig[entry] != OP_N) { + if (reason = get_ops (op_eig[entry], op, intrq)) /* get instruction operands */ + return reason; + } -switch (entry) { /* decode IR<4:0> */ +switch (entry) { /* decode IR<4:0> */ /* EIG module 1 */ -case 000: /* SAX, SBX 10x740 (OP_A) */ - op[0] = (op[0] + XR) & VAMASK; /* indexed addr */ - WriteW (op[0], ABREG[absel]); /* store */ - break; + case 000: /* SAX, SBX 10x740 (OP_A) */ + op[0] = (op[0] + XR) & VAMASK; /* indexed addr */ + WriteW (op[0], ABREG[absel]); /* store */ + break; -case 001: /* CAX, CBX 10x741 (OP_N) */ - XR = ABREG[absel]; /* copy to XR */ - break; + case 001: /* CAX, CBX 10x741 (OP_N) */ + XR = ABREG[absel]; /* copy to XR */ + break; -case 002: /* LAX, LBX 10x742 (OP_A) */ - op[0] = (op[0] + XR) & VAMASK; /* indexed addr */ - ABREG[absel] = ReadW (op[0]); /* load */ - break; + case 002: /* LAX, LBX 10x742 (OP_A) */ + op[0] = (op[0] + XR) & VAMASK; /* indexed addr */ + ABREG[absel] = ReadW (op[0]); /* load */ + break; -case 003: /* STX 105743 (OP_A) */ - WriteW (op[0], XR); /* store XR */ - break; + case 003: /* STX 105743 (OP_A) */ + WriteW (op[0], XR); /* store XR */ + break; -case 004: /* CXA, CXB 10x744 (OP_N) */ - ABREG[absel] = XR; /* copy from XR */ - break; + case 004: /* CXA, CXB 10x744 (OP_N) */ + ABREG[absel] = XR; /* copy from XR */ + break; -case 005: /* LDX 105745 (OP_K)*/ - XR = op[0]; /* load XR */ - break; + case 005: /* LDX 105745 (OP_K)*/ + XR = op[0]; /* load XR */ + break; -case 006: /* ADX 105746 (OP_K) */ - t = XR + op[0]; /* add to XR */ - if (t > DMASK) E = 1; /* set E, O */ - if (((~XR ^ op[0]) & (XR ^ t)) & SIGN) O = 1; - XR = t & DMASK; - break; + case 006: /* ADX 105746 (OP_K) */ + t = XR + op[0]; /* add to XR */ + if (t > DMASK) E = 1; /* set E, O */ + if (((~XR ^ op[0]) & (XR ^ t)) & SIGN) O = 1; + XR = t & DMASK; + break; -case 007: /* XAX, XBX 10x747 (OP_N) */ - t = XR; /* exchange XR */ - XR = ABREG[absel]; - ABREG[absel] = t; - break; + case 007: /* XAX, XBX 10x747 (OP_N) */ + t = XR; /* exchange XR */ + XR = ABREG[absel]; + ABREG[absel] = t; + break; -case 010: /* SAY, SBY 10x750 (OP_A) */ - op[0] = (op[0] + YR) & VAMASK; /* indexed addr */ - WriteW (op[0], ABREG[absel]); /* store */ - break; + case 010: /* SAY, SBY 10x750 (OP_A) */ + op[0] = (op[0] + YR) & VAMASK; /* indexed addr */ + WriteW (op[0], ABREG[absel]); /* store */ + break; -case 011: /* CAY, CBY 10x751 (OP_N) */ - YR = ABREG[absel]; /* copy to YR */ - break; + case 011: /* CAY, CBY 10x751 (OP_N) */ + YR = ABREG[absel]; /* copy to YR */ + break; -case 012: /* LAY, LBY 10x752 (OP_A) */ - op[0] = (op[0] + YR) & VAMASK; /* indexed addr */ - ABREG[absel] = ReadW (op[0]); /* load */ - break; + case 012: /* LAY, LBY 10x752 (OP_A) */ + op[0] = (op[0] + YR) & VAMASK; /* indexed addr */ + ABREG[absel] = ReadW (op[0]); /* load */ + break; -case 013: /* STY 105753 (OP_A) */ - WriteW (op[0], YR); /* store YR */ - break; + case 013: /* STY 105753 (OP_A) */ + WriteW (op[0], YR); /* store YR */ + break; -case 014: /* CYA, CYB 10x754 (OP_N) */ - ABREG[absel] = YR; /* copy from YR */ - break; + case 014: /* CYA, CYB 10x754 (OP_N) */ + ABREG[absel] = YR; /* copy from YR */ + break; -case 015: /* LDY 105755 (OP_K) */ - YR = op[0]; /* load YR */ - break; + case 015: /* LDY 105755 (OP_K) */ + YR = op[0]; /* load YR */ + break; -case 016: /* ADY 105756 (OP_K) */ - t = YR + op[0]; /* add to YR */ - if (t > DMASK) E = 1; /* set E, O */ - if (((~YR ^ op[0]) & (YR ^ t)) & SIGN) O = 1; - YR = t & DMASK; - break; + case 016: /* ADY 105756 (OP_K) */ + t = YR + op[0]; /* add to YR */ + if (t > DMASK) E = 1; /* set E, O */ + if (((~YR ^ op[0]) & (YR ^ t)) & SIGN) O = 1; + YR = t & DMASK; + break; + + case 017: /* XAY, XBY 10x757 (OP_N) */ + t = YR; /* exchange YR */ + YR = ABREG[absel]; + ABREG[absel] = t; + break; -case 017: /* XAY, XBY 10x757 (OP_N) */ - t = YR; /* exchange YR */ - YR = ABREG[absel]; - ABREG[absel] = t; - break; - /* EIG module 2 */ -case 020: /* ISX 105760 (OP_N) */ - XR = (XR + 1) & DMASK; /* incr XR */ - if (XR == 0) PC = (PC + 1) & VAMASK; /* skip if zero */ - break; + case 020: /* ISX 105760 (OP_N) */ + XR = (XR + 1) & DMASK; /* incr XR */ + if (XR == 0) PC = (PC + 1) & VAMASK; /* skip if zero */ + break; -case 021: /* DSX 105761 (OP_N) */ - XR = (XR - 1) & DMASK; /* decr XR */ - if (XR == 0) PC = (PC + 1) & VAMASK; /* skip if zero */ - break; + case 021: /* DSX 105761 (OP_N) */ + XR = (XR - 1) & DMASK; /* decr XR */ + if (XR == 0) PC = (PC + 1) & VAMASK; /* skip if zero */ + break; -case 022: /* JLY 105762 (OP_A) */ - mp_dms_jmp (op[0]); /* validate jump addr */ - PCQ_ENTRY; - YR = PC; /* ret addr to YR */ - PC = op[0]; /* jump */ - break; + case 022: /* JLY 105762 (OP_A) */ + mp_dms_jmp (op[0]); /* validate jump addr */ + PCQ_ENTRY; + YR = PC; /* ret addr to YR */ + PC = op[0]; /* jump */ + break; -case 023: /* LBT 105763 (OP_N) */ - AR = ReadB (BR); /* load byte */ - BR = (BR + 1) & DMASK; /* incr ptr */ - break; + case 023: /* LBT 105763 (OP_N) */ + AR = ReadB (BR); /* load byte */ + BR = (BR + 1) & DMASK; /* incr ptr */ + break; -case 024: /* SBT 105764 (OP_N) */ - WriteB (BR, AR); /* store byte */ - BR = (BR + 1) & DMASK; /* incr ptr */ - break; + case 024: /* SBT 105764 (OP_N) */ + WriteB (BR, AR); /* store byte */ + BR = (BR + 1) & DMASK; /* incr ptr */ + break; -case 025: /* MBT 105765 (OP_KV) */ - wc = ReadW (op[1]); /* get continuation count */ - if (wc == 0) wc = op[0]; /* none? get initiation count */ - if ((wc & SIGN) && (UNIT_CPU_TYPE == UNIT_TYPE_2100)) - break; /* < 0 is NOP for 2100 IOP */ - while (wc != 0) { /* while count */ - WriteW (op[1], wc); /* for MP 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 (op[1], wc); /* clean up inline */ - break; + case 025: /* MBT 105765 (OP_KV) */ + wc = ReadW (op[1]); /* get continuation count */ + if (wc == 0) wc = op[0]; /* none? get initiation count */ + if ((wc & SIGN) && (UNIT_CPU_TYPE == UNIT_TYPE_2100)) + break; /* < 0 is NOP for 2100 IOP */ + while (wc != 0) { /* while count */ + WriteW (op[1], wc); /* for MP 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; + } + } + WriteW (op[1], wc); /* clean up inline */ + break; -case 026: /* CBT 105766 (OP_KV) */ - wc = ReadW (op[1]); /* get continuation count */ - if (wc == 0) wc = op[0]; /* none? get initiation count */ - while (wc != 0) { /* while count */ - WriteW (op[1], wc); /* for MP 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 (op[1], wc); /* clean up inline */ - break; + case 026: /* CBT 105766 (OP_KV) */ + wc = ReadW (op[1]); /* get continuation count */ + if (wc == 0) wc = op[0]; /* none? get initiation count */ + while (wc != 0) { /* while count */ + WriteW (op[1], wc); /* for MP 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; + } + } + WriteW (op[1], wc); /* clean up inline */ + break; -case 027: /* SFB 105767 (OP_N) */ - 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; + case 027: /* SFB 105767 (OP_N) */ + 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; + } + } + break; -case 030: /* ISY 105770 (OP_N) */ - YR = (YR + 1) & DMASK; /* incr YR */ - if (YR == 0) PC = (PC + 1) & VAMASK; /* skip if zero */ - break; + case 030: /* ISY 105770 (OP_N) */ + YR = (YR + 1) & DMASK; /* incr YR */ + if (YR == 0) PC = (PC + 1) & VAMASK; /* skip if zero */ + break; -case 031: /* DSY 105771 (OP_N) */ - YR = (YR - 1) & DMASK; /* decr YR */ - if (YR == 0) PC = (PC + 1) & VAMASK; /* skip if zero */ - break; + case 031: /* DSY 105771 (OP_N) */ + YR = (YR - 1) & DMASK; /* decr YR */ + if (YR == 0) PC = (PC + 1) & VAMASK; /* skip if zero */ + break; -case 032: /* JPY 105772 (OP_C) */ - op[0] = (op[0] + YR) & VAMASK; /* index, no indir */ - mp_dms_jmp (op[0]); /* validate jump addr */ - PCQ_ENTRY; - PC = op[0]; /* jump */ - break; + case 032: /* JPY 105772 (OP_C) */ + op[0] = (op[0] + YR) & VAMASK; /* index, no indir */ + mp_dms_jmp (op[0]); /* validate jump addr */ + PCQ_ENTRY; + PC = op[0]; /* jump */ + break; -case 033: /* SBS 105773 (OP_KA) */ - WriteW (op[1], ReadW (op[1]) | op[0]); /* set bits */ - break; + case 033: /* SBS 105773 (OP_KA) */ + WriteW (op[1], ReadW (op[1]) | op[0]); /* set bits */ + break; -case 034: /* CBS 105774 (OP_KA) */ - WriteW (op[1], ReadW (op[1]) & ~op[0]); /* clear bits */ - break; + case 034: /* CBS 105774 (OP_KA) */ + WriteW (op[1], ReadW (op[1]) & ~op[0]); /* clear bits */ + break; -case 035: /* TBS 105775 (OP_KK) */ - if ((op[1] & op[0]) != op[0]) /* test bits */ - PC = (PC + 1) & VAMASK; - break; + case 035: /* TBS 105775 (OP_KK) */ + if ((op[1] & op[0]) != op[0]) /* test bits */ + PC = (PC + 1) & VAMASK; + break; -case 036: /* CMW 105776 (OP_KV) */ - wc = ReadW (op[1]); /* get continuation count */ - if (wc == 0) wc = op[0]; /* none? get initiation count */ - while (wc != 0) { /* while count */ - WriteW (op[1], 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 (op[1], wc); /* clean up inline */ - break; + case 036: /* CMW 105776 (OP_KV) */ + wc = ReadW (op[1]); /* get continuation count */ + if (wc == 0) wc = op[0]; /* none? get initiation count */ + while (wc != 0) { /* while count */ + WriteW (op[1], 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; + } + } + WriteW (op[1], wc); /* clean up inline */ + break; -case 037: /* MVW 105777 (OP_KV) */ - wc = ReadW (op[1]); /* get continuation count */ - if (wc == 0) wc = op[0]; /* none? get initiation count */ - if ((wc & SIGN) && (UNIT_CPU_TYPE == UNIT_TYPE_2100)) - break; /* < 0 is NOP for 2100 IOP */ - while (wc != 0) { /* while count */ - WriteW (op[1], 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 (op[1], wc); /* clean up inline */ - break; + case 037: /* MVW 105777 (OP_KV) */ + wc = ReadW (op[1]); /* get continuation count */ + if (wc == 0) wc = op[0]; /* none? get initiation count */ + if ((wc & SIGN) && (UNIT_CPU_TYPE == UNIT_TYPE_2100)) + break; /* < 0 is NOP for 2100 IOP */ + while (wc != 0) { /* while count */ + WriteW (op[1], 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; + } + } + WriteW (op[1], wc); /* clean up inline */ + break; -default: /* all others NOP */ - break; } + default: /* all others NOP */ + break; + } return reason; } - + /* Get instruction operands Operands for a given instruction are specifed by an "operand pattern" @@ -1778,40 +1857,40 @@ return reason; Eight operand encodings are defined: - Code Operand Description Example Return + Code Operand Description Example Return ------ ----------------------------- ----------- ------------ - OP_NUL No operand present [inst] None + OP_NUL No operand present [inst] None - OP_CON Inline constant [inst] Value of C - C DEC 0 + OP_CON Inline constant [inst] Value of C + C DEC 0 - OP_VAR Inline variable [inst] Address of V - V BSS 1 + OP_VAR Inline variable [inst] Address of V + V BSS 1 - OP_ADR Address [inst] Address of A - DEF A - ... - A EQU * - - OP_ADK Address of a 1-word constant [instr] Value of K - DEF K - ... - K DEC 0 + OP_ADR Address [inst] Address of A + DEF A + ... + A EQU * + + OP_ADK Address of a 1-word constant [instr] Value of K + DEF K + ... + K DEC 0 - OP_ADF Address of a 2-word constant [inst] Value of F - DEF F - ... - F DEC 0.0 + OP_ADF Address of a 2-word constant [inst] Value of F + DEF F + ... + F DEC 0.0 - OP_ADX Address of a 3-word constant [inst] Value of X - DEF X - ... - X DEX 0.0 + OP_ADX Address of a 3-word constant [inst] Value of X + DEF X + ... + X DEX 0.0 - OP_ADT Address of a 4-word constant [inst] Value of T - DEF T - ... - T DEY 0.0 + OP_ADT Address of a 4-word constant [inst] Value of T + DEF T + ... + T DEY 0.0 Address operands, i.e., those having a DEF to the operand, will be resolved to direct addresses. If an interrupt is pending and more than three levels @@ -1838,49 +1917,50 @@ uint32 i, MA; XPN xop; for (i = 0; i < OP_N_F; i++) { - flags = pattern & OP_M_FLAGS; /* get operand pattern */ + flags = pattern & OP_M_FLAGS; /* get operand pattern */ - if (flags >= OP_ADR) /* address operand? */ - if (reason = resolve (ReadW (PC), &MA, irq))/* resolve indirects */ - return reason; + if (flags >= OP_ADR) /* address operand? */ + if (reason = resolve (ReadW (PC), &MA, irq)) /* resolve indirects */ + return reason; - switch (flags) { - case OP_NUL: /* null operand */ - return reason; /* no more, so quit */ + switch (flags) { + case OP_NUL: /* null operand */ + return reason; /* no more, so quit */ - case OP_CON: /* constant operand */ - *op++ = ReadW (PC); /* get value */ - break; + case OP_CON: /* constant operand */ + *op++ = ReadW (PC); /* get value */ + break; - case OP_VAR: /* variable operand */ - *op++ = PC; /* get pointer to variable */ - break; + case OP_VAR: /* variable operand */ + *op++ = PC; /* get pointer to variable */ + break; - case OP_ADR: /* address operand */ - *op++ = MA; /* get address */ - break; + case OP_ADR: /* address operand */ + *op++ = MA; /* get address */ + break; - case OP_ADK: /* address of 1-word constant */ - *op++ = ReadW (MA); /* get value */ - break; + case OP_ADK: /* address of 1-word constant */ + *op++ = ReadW (MA); /* get value */ + break; - case OP_ADF: /* address of 2-word constant */ - *op++ = ReadF (MA); /* get value */ - break; + case OP_ADF: /* address of 2-word constant */ + *op++ = ReadF (MA); /* get value */ + break; - case OP_ADX: /* address of 3-word constant */ - xop = ReadX (MA); - *op++ = xop.high; /* get first two words of value */ - *op++ = xop.low; /* get third word of value */ - break; + case OP_ADX: /* address of 3-word constant */ + xop = ReadX (MA); + *op++ = xop.high; /* get first two words of value */ + *op++ = xop.low; /* get third word of value */ + break; - case OP_ADT: /* address of 4-word constant */ + case OP_ADT: /* address of 4-word constant */ - default: - return SCPE_IERR; /* not implemented */ - } + default: + return SCPE_IERR; /* not implemented */ + } - PC = (PC + 1) & VAMASK; - pattern = pattern >> OP_N_FLAGS; } /* move next pattern into place */ + PC = (PC + 1) & VAMASK; + pattern = pattern >> OP_N_FLAGS; /* move next pattern into place */ + } return reason; } diff --git a/HP2100/hp2100_defs.h b/HP2100/hp2100_defs.h index 289412cb..c56e5205 100644 --- a/HP2100/hp2100_defs.h +++ b/HP2100/hp2100_defs.h @@ -23,266 +23,266 @@ 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-Dec-04 JDB Added IBL_DS_HEAD head number mask - 19-Nov-04 JDB Added STOP_OFFLINE, STOP_PWROFF stop codes - 25-Apr-04 RMS Added additional IBL definitions - Added DMA EDT I/O pseudo-opcode - 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 + 30-Dec-04 JDB Added IBL_DS_HEAD head number mask + 19-Nov-04 JDB Added STOP_OFFLINE, STOP_PWROFF stop codes + 25-Apr-04 RMS Added additional IBL definitions + Added DMA EDT I/O pseudo-opcode + 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; and of Dave Bryan in adding features and correcting errors throughout the simulator. */ +#ifndef _HP2100_DEFS_H_ +#define _HP2100_DEFS_H_ 0 -#include "sim_defs.h" /* simulator defns */ +#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 STOP_OFFLINE 8 /* device offline */ -#define STOP_PWROFF 9 /* device powered off */ +#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 STOP_OFFLINE 8 /* device offline */ +#define STOP_PWROFF 9 /* device powered off */ -#define ABORT_PRO 1 /* protection abort */ +#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 077777 /* virt addr mask */ -#define PA_N_SIZE 20 /* phys addr size */ -#define PASIZE (1 << PA_N_SIZE) -#define PAMASK (PASIZE - 1) /* phys addr mask */ +#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 077777 /* 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 ABREG[0] /* A = reg 0 */ -#define BR ABREG[1] /* B = reg 1 */ -#define SEXT(x) ((int32) (((x) & SIGN)? ((x) | ~DMASK): ((x) & DMASK))) +#define SIGN32 020000000000 /* 32b sign */ +#define SIGN 0100000 /* 16b sign */ +#define DMASK 0177777 /* 16b data mask */ +#define AR ABREG[0] /* A = reg 0 */ +#define BR ABREG[1] /* B = reg 1 */ +#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 */ +#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 0172000 /* 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 */ +#define I_NMRMASK 0172000 /* 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 */ +#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 */ + uint32 cw1; /* device select */ + uint32 cw2; /* direction, address */ + uint32 cw3; /* word count */ + }; -struct DMA { /* DMA channel */ - uint32 cw1; /* device select */ - uint32 cw2; /* direction, address */ - uint32 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) +#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 */ +#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 */ /* DMS map entries */ -#define MAP_V_RPR 15 /* read prot */ -#define MAP_V_WPR 14 /* write prot */ -#define RD (1 << MAP_V_RPR) -#define WR (1 << MAP_V_WPR) -#define MAP_MBZ 0036000 /* must be zero */ -#define MAP_N_PAG (PA_N_SIZE - VA_N_OFF) /* page width */ -#define MAP_V_PAG (VA_N_OFF) -#define MAP_M_PAG ((1 << MAP_N_PAG) - 1) -#define MAP_GETPAG(x) (((x) & MAP_M_PAG) << MAP_V_PAG) +#define MAP_V_RPR 15 /* read prot */ +#define MAP_V_WPR 14 /* write prot */ +#define RD (1 << MAP_V_RPR) +#define WR (1 << MAP_V_WPR) +#define MAP_MBZ 0036000 /* must be zero */ +#define MAP_N_PAG (PA_N_SIZE - VA_N_OFF) /* page width */ +#define MAP_V_PAG (VA_N_OFF) +#define MAP_M_PAG ((1 << MAP_N_PAG) - 1) +#define MAP_GETPAG(x) (((x) & MAP_M_PAG) << MAP_V_PAG) /* 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 */ +#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 /* must be same as */ -#define MVI_V_WPR 14 /* MAP_V_xPR */ -#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 */ - +#define MVI_V_RPR 15 /* must be same as */ +#define MVI_V_WPR 14 /* MAP_V_xPR */ +#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 */ +#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 */ -#define ioEDT 8 /* DMA: end data transfer */ +#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 */ +#define ioEDT 8 /* DMA: end data transfer */ /* 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)) +#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 /* 12597A-002 paper tape reader */ -#define TTY 011 /* 12531C teleprinter */ -#define PTP 012 /* 12597A-005 paper tape punch */ -#define CLK 013 /* 12539C time-base generator */ -#define LPS 014 /* 12653A line printer */ -#define LPT 015 /* 12845A 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 /* 12566B link in */ -#define IPLO 033 /* 12566B link out */ -#define DS 034 /* 13037A control */ -#define MUXL 040 /* 12920A lower data */ -#define MUXU 041 /* 12920A upper data */ -#define MUXC 042 /* 12920A control */ +#define PTR 010 /* 12597A-002 paper tape reader */ +#define TTY 011 /* 12531C teleprinter */ +#define PTP 012 /* 12597A-005 paper tape punch */ +#define CLK 013 /* 12539C time-base generator */ +#define LPS 014 /* 12653A line printer */ +#define LPT 015 /* 12845A 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 /* 12566B link in */ +#define IPLO 033 /* 12566B link out */ +#define DS 034 /* 13037A control */ +#define MUXL 040 /* 12920A lower data */ +#define MUXU 041 /* 12920A upper data */ +#define MUXC 042 /* 12920A control */ /* IBL assignments */ -#define IBL_V_SEL 14 /* ROM select */ -#define IBL_M_SEL 03 -#define IBL_PTR 0000000 /* PTR */ -#define IBL_DP 0040000 /* disk: DP */ -#define IBL_DQ 0060000 /* disk: DQ */ -#define IBL_MS 0100000 /* option 0: MS */ -#define IBL_DS 0140000 /* option 1: DS */ -#define IBL_MAN 0010000 /* RPL/man boot */ -#define IBL_V_DEV 6 /* dev in <11:6> */ -#define IBL_OPT 0000070 /* options in <5:3> */ -#define IBL_DP_REM 0000001 /* DP removable */ -#define IBL_DS_HEAD 0000003 /* DS head number */ -#define IBL_LNT 64 /* boot length */ -#define IBL_MASK (IBL_LNT - 1) /* boot length mask */ -#define IBL_DPC (IBL_LNT - 2) /* DMA ctrl word */ -#define IBL_END (IBL_LNT - 1) /* last location */ +#define IBL_V_SEL 14 /* ROM select */ +#define IBL_M_SEL 03 +#define IBL_PTR 0000000 /* PTR */ +#define IBL_DP 0040000 /* disk: DP */ +#define IBL_DQ 0060000 /* disk: DQ */ +#define IBL_MS 0100000 /* option 0: MS */ +#define IBL_DS 0140000 /* option 1: DS */ +#define IBL_MAN 0010000 /* RPL/man boot */ +#define IBL_V_DEV 6 /* dev in <11:6> */ +#define IBL_OPT 0000070 /* options in <5:3> */ +#define IBL_DP_REM 0000001 /* DP removable */ +#define IBL_DS_HEAD 0000003 /* DS head number */ +#define IBL_LNT 64 /* boot length */ +#define IBL_MASK (IBL_LNT - 1) /* boot length mask */ +#define IBL_DPC (IBL_LNT - 2) /* DMA ctrl word */ +#define IBL_END (IBL_LNT - 1) /* last location */ /* Dynamic device information table */ -struct hp_dib { - uint32 devno; /* device number */ - uint32 cmd; /* saved command */ - uint32 ctl; /* saved control */ - uint32 flg; /* saved flag */ - uint32 fbf; /* saved flag buf */ - uint32 srq; /* saved svc req */ - int32 (*iot)(int32 op, int32 ir, int32 dat); /* I/O routine */ -}; - -typedef struct hp_dib DIB; +typedef struct { + uint32 devno; /* device number */ + uint32 cmd; /* saved command */ + uint32 ctl; /* saved control */ + uint32 flg; /* saved flag */ + uint32 fbf; /* saved flag buf */ + uint32 srq; /* saved svc req */ + int32 (*iot)(int32 op, int32 ir, int32 dat); /* I/O routine */ + } 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 setFSR(D) dev_flg[(D)/32] = dev_flg[(D)/32] | INT_M (D); \ - setFBF(D); setSRQ(D) -#define clrFSR(D) dev_flg[(D)/32] = dev_flg[(D)/32] & ~INT_M (D); \ - clrFBF(D); clrSRQ(D) -#define setSRQ(D) dev_srq[(D)/32] = dev_srq[(D)/32] | INT_M ((D)) -#define clrSRQ(D) dev_srq[(D)/32] = dev_srq[(D)/32] & ~INT_M (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 SRQ(D) ((dev_srq[(D)/32] >> INT_V (D)) & 1) +#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 setFSR(D) dev_flg[(D)/32] = dev_flg[(D)/32] | INT_M (D); \ + setFBF(D); setSRQ(D) +#define clrFSR(D) dev_flg[(D)/32] = dev_flg[(D)/32] & ~INT_M (D); \ + clrFBF(D); clrSRQ(D) +#define setSRQ(D) dev_srq[(D)/32] = dev_srq[(D)/32] | INT_M ((D)) +#define clrSRQ(D) dev_srq[(D)/32] = dev_srq[(D)/32] & ~INT_M (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 SRQ(D) ((dev_srq[(D)/32] >> INT_V (D)) & 1) -#define IOT_V_REASON 16 -#define IORETURN(f,v) ((f)? (v): SCPE_OK) /* stop on error */ +#define IOT_V_REASON 16 +#define IORETURN(f,v) ((f)? (v): SCPE_OK) /* stop on error */ /* Function prototypes */ @@ -290,3 +290,5 @@ t_stat ibl_copy (const uint16 pboot[IBL_LNT], int32 dev); 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); + +#endif diff --git a/HP2100/hp2100_doc.txt b/HP2100/hp2100_doc.txt index d3174ca5..75e2aef5 100644 --- a/HP2100/hp2100_doc.txt +++ b/HP2100/hp2100_doc.txt @@ -1,7 +1,7 @@ To: Users From: Bob Supnik Subj: HP2100 Simulator Usage -Date: 20-Jan-2005 +Date: 01-Jul-2005 COPYRIGHT NOTICE @@ -694,8 +694,7 @@ 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. +active connections. The SET MUXLn DISCONNECT command disconnects line n. The scanner (MUX) implements these registers: diff --git a/HP2100/hp2100_dp.c b/HP2100/hp2100_dp.c index f210072e..816aa3c4 100644 --- a/HP2100/hp2100_dp.c +++ b/HP2100/hp2100_dp.c @@ -1,6 +1,6 @@ /* hp2100_dp.c: HP 2100 12557A/13210A disk simulator - Copyright (c) 1993-2004, Robert M. Supnik + Copyright (c) 1993-2005, 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"), @@ -19,53 +19,53 @@ 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 + 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 + dp 12557A 2871 disk subsystem + 13210A 7900 disk subsystem - 01-Mar-05 JDB Added SET UNLOAD/LOAD - 07-Oct-04 JDB Fixed enable/disable from either device - Fixed ANY ERROR status for 12557A interface - Fixed unattached drive status for 12557A interface - Status cmd without prior STC DC now completes (12557A) - OTA/OTB CC on 13210A interface also does CLC CC - Fixed RAR model - Fixed seek check on 13210 if sector out of range - 20-Aug-04 JDB Fixes from Dave Bryan - - Check status on unattached drive set busy and not ready - - Check status tests wrong unit for write protect status - - Drive on line sets ATN, will set FLG if polling - 15-Aug-04 RMS Controller resumes polling for ATN interrupts after - read status (found by Dave Bryan) - 22-Jul-04 RMS Controller sets ATN for all commands except - read status (found by Dave Bryan) - 21-Apr-04 RMS Fixed typo in boot loader (found by Dave Bryan) - 26-Apr-04 RMS Fixed SFS x,C and SFC x,C - Fixed SR setting in IBL - Fixed interpretation of SR<0> - Revised IBL loader - Implemented DMA SRQ (follows FLG) - 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 + 01-Mar-05 JDB Added SET UNLOAD/LOAD + 07-Oct-04 JDB Fixed enable/disable from either device + Fixed ANY ERROR status for 12557A interface + Fixed unattached drive status for 12557A interface + Status cmd without prior STC DC now completes (12557A) + OTA/OTB CC on 13210A interface also does CLC CC + Fixed RAR model + Fixed seek check on 13210 if sector out of range + 20-Aug-04 JDB Fixes from Dave Bryan + - Check status on unattached drive set busy and not ready + - Check status tests wrong unit for write protect status + - Drive on line sets ATN, will set FLG if polling + 15-Aug-04 RMS Controller resumes polling for ATN interrupts after + read status (found by Dave Bryan) + 22-Jul-04 RMS Controller sets ATN for all commands except + read status (found by Dave Bryan) + 21-Apr-04 RMS Fixed typo in boot loader (found by Dave Bryan) + 26-Apr-04 RMS Fixed SFS x,C and SFC x,C + Fixed SR setting in IBL + Fixed interpretation of SR<0> + Revised IBL loader + Implemented DMA SRQ (follows FLG) + 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 The simulator uses a number of state variables: - dpc_busy set to drive number + 1 when the controller is busy - of the unit in use - dpd_xfer set to 1 if the data channel is executing a data transfer - dpd_wval set to 1 by OTx if either !dpc_busy or dpd_xfer - dpc_poll set to 1 if attention polling is enabled + dpc_busy set to drive number + 1 when the controller is busy + of the unit in use + dpd_xfer set to 1 if the data channel is executing a data transfer + dpd_wval set to 1 by OTx if either !dpc_busy or dpd_xfer + dpc_poll set to 1 if attention polling is enabled dpc_busy and dpd_xfer are set together at the start of a read, write, refine, or init. When data transfers are complete (CLC DC), dpd_xfer is cleared, but the @@ -113,120 +113,120 @@ #include "hp2100_defs.h" -#define UNIT_V_WLK (UNIT_V_UF + 0) /* write locked */ -#define UNIT_V_UNLOAD (UNIT_V_UF + 1) /* heads unloaded */ -#define UNIT_WLK (1 << UNIT_V_WLK) -#define UNIT_UNLOAD (1 << UNIT_V_UNLOAD) -#define FNC u3 /* saved function */ -#define DRV u4 /* drive number (DC) */ -#define UNIT_WPRT (UNIT_WLK | UNIT_RO) /* write prot */ +#define UNIT_V_WLK (UNIT_V_UF + 0) /* write locked */ +#define UNIT_V_UNLOAD (UNIT_V_UF + 1) /* heads unloaded */ +#define UNIT_WLK (1 << UNIT_V_WLK) +#define UNIT_UNLOAD (1 << UNIT_V_UNLOAD) +#define FNC u3 /* saved function */ +#define DRV u4 /* drive number (DC) */ +#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 */ +#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) +#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) +#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_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_ERSET2 (STA_1ST | STA_OVR | STA_RWU | STA_ACU | \ - STA_SKI | STA_SKE | STA_NRDY | \ - STA_EOC | STA_AER | STA_DTE) /* 12557A error set */ -#define STA_ERSET3 (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) /* 13210A error set */ -#define STA_ANYERR (dp_ctype ? STA_ERSET3 : STA_ERSET2) +#define STA_ERSET2 (STA_1ST | STA_OVR | STA_RWU | STA_ACU | \ + STA_SKI | STA_SKE | STA_NRDY | \ + STA_EOC | STA_AER | STA_DTE) /* 12557A error set */ +#define STA_ERSET3 (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) /* 13210A error set */ +#define STA_ANYERR (dp_ctype ? STA_ERSET3 : STA_ERSET2) + +#define STA_UNLOADED (dp_ctype ? (STA_NRDY | STA_BSY) : STA_NRDY) +#define STA_MBZ13 (STA_ATN | STA_RWU | STA_SKI) /* zero in 13210 */ -#define STA_UNLOADED (dp_ctype ? (STA_NRDY | STA_BSY) : STA_NRDY) -#define STA_MBZ13 (STA_ATN | STA_RWU | STA_SKI) /* zero in 13210 */ - extern uint32 PC, SR; extern uint32 dev_cmd[2], dev_ctl[2], dev_flg[2], dev_fbf[2], dev_srq[2]; extern int32 sim_switches; extern UNIT cpu_unit; -int32 dp_ctype = 1; /* ctrl type */ -int32 dpc_busy = 0; /* cch unit */ -int32 dpc_poll = 0; /* cch poll enable */ -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 = 0; /* RAR cylinder */ -uint8 dpc_rarh = 0; /* RAR head */ -uint8 dpc_rars = 0; /* RAR sector */ -uint8 dpc_ucyl[DP_NUMDRV] = { 0 }; /* unit cylinder */ -uint16 dpc_sta[DP_NUMDRV] = { 0 }; /* status regs */ -uint16 dpxb[DP_NUMWD]; /* sector buffer */ +int32 dp_ctype = 1; /* ctrl type */ +int32 dpc_busy = 0; /* cch unit */ +int32 dpc_poll = 0; /* cch poll enable */ +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 = 0; /* RAR cylinder */ +uint8 dpc_rarh = 0; /* RAR head */ +uint8 dpc_rars = 0; /* RAR sector */ +uint8 dpc_ucyl[DP_NUMDRV] = { 0 }; /* unit cylinder */ +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); @@ -242,17 +242,18 @@ void dp_goc (int32 fnc, int32 drv, int32 time); t_stat dpc_load_unload (UNIT *uptr, int32 value, char *cptr, void *desc); 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 + dpd_dev DPD device descriptor + dpd_unit DPD unit list + dpd_reg DPD register list */ DIB dp_dib[] = { - { DPD, 0, 0, 0, 0, 0, &dpdio }, - { DPC, 0, 0, 0, 0, 0, &dpcio } }; + { DPD, 0, 0, 0, 0, 0, &dpdio }, + { DPC, 0, 0, 0, 0, 0, &dpcio } + }; #define dpd_dib dp_dib[0] #define dpc_dib dp_dib[1] @@ -260,215 +261,248 @@ DIB dp_dib[] = { UNIT dpd_unit = { UDATA (&dpd_svc, 0, 0) }; REG dpd_reg[] = { - { ORDATA (IBUF, dpd_ibuf, 16) }, - { ORDATA (OBUF, dpd_obuf, 16) }, - { BRDATA (DBUF, dpxb, 8, 16, DP_NUMWD) }, - { DRDATA (BPTR, dp_ptr, DP_N_NUMWD) }, - { 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 (SRQ, dpd_dib.srq, 0) }, - { FLDATA (XFER, dpd_xfer, 0) }, - { FLDATA (WVAL, dpd_wval, 0) }, - { ORDATA (DEVNO, dpd_dib.devno, 6), REG_HRO }, - { NULL } }; + { ORDATA (IBUF, dpd_ibuf, 16) }, + { ORDATA (OBUF, dpd_obuf, 16) }, + { BRDATA (DBUF, dpxb, 8, 16, DP_NUMWD) }, + { DRDATA (BPTR, dp_ptr, DP_N_NUMWD) }, + { 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 (SRQ, dpd_dib.srq, 0) }, + { FLDATA (XFER, dpd_xfer, 0) }, + { FLDATA (WVAL, dpd_wval, 0) }, + { 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 } }; + { 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, DEV_DISABLE }; + "DPD", &dpd_unit, dpd_reg, dpd_mod, + 1, 10, DP_N_NUMWD, 1, 8, 16, + NULL, NULL, &dpc_reset, + NULL, NULL, NULL, + &dpd_dib, DEV_DISABLE + }; /* DPC data structures - dpc_dev DPC device descriptor - dpc_unit DPC unit list - dpc_reg DPC register list - dpc_mod DPC modifier list + 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_ROABLE | - UNIT_DISABLE | UNIT_UNLOAD, DP_SIZE3) }, - { UDATA (&dpc_svc, UNIT_FIX | UNIT_ATTABLE | UNIT_ROABLE | - UNIT_DISABLE | UNIT_UNLOAD, DP_SIZE3) }, - { UDATA (&dpc_svc, UNIT_FIX | UNIT_ATTABLE | UNIT_ROABLE | - UNIT_DISABLE | UNIT_UNLOAD, DP_SIZE3) }, - { UDATA (&dpc_svc, UNIT_FIX | UNIT_ATTABLE | UNIT_ROABLE | - UNIT_DISABLE | UNIT_UNLOAD, DP_SIZE3) } }; + { UDATA (&dpc_svc, UNIT_FIX | UNIT_ATTABLE | UNIT_ROABLE | + UNIT_DISABLE | UNIT_UNLOAD, DP_SIZE3) }, + { UDATA (&dpc_svc, UNIT_FIX | UNIT_ATTABLE | UNIT_ROABLE | + UNIT_DISABLE | UNIT_UNLOAD, DP_SIZE3) }, + { UDATA (&dpc_svc, UNIT_FIX | UNIT_ATTABLE | UNIT_ROABLE | + UNIT_DISABLE | UNIT_UNLOAD, DP_SIZE3) }, + { UDATA (&dpc_svc, UNIT_FIX | UNIT_ATTABLE | UNIT_ROABLE | + UNIT_DISABLE | UNIT_UNLOAD, DP_SIZE3) } + }; REG dpc_reg[] = { - { ORDATA (OBUF, dpc_obuf, 16) }, - { ORDATA (BUSY, dpc_busy, 4), 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 (SRQ, dpc_dib.srq, 0) }, - { FLDATA (EOC, dpc_eoc, 0) }, - { FLDATA (POLL, dpc_poll, 0) }, - { DRDATA (RARC, dpc_rarc, 8), PV_RZRO }, - { DRDATA (RARH, dpc_rarh, 2), PV_RZRO }, - { DRDATA (RARS, dpc_rars, 5), PV_RZRO }, - { BRDATA (CYL, dpc_ucyl, 10, 8, DP_NUMDRV), PV_RZRO }, - { 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 (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 } }; + { ORDATA (OBUF, dpc_obuf, 16) }, + { ORDATA (BUSY, dpc_busy, 4), 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 (SRQ, dpc_dib.srq, 0) }, + { FLDATA (EOC, dpc_eoc, 0) }, + { FLDATA (POLL, dpc_poll, 0) }, + { DRDATA (RARC, dpc_rarc, 8), PV_RZRO }, + { DRDATA (RARH, dpc_rarh, 2), PV_RZRO }, + { DRDATA (RARS, dpc_rars, 5), PV_RZRO }, + { BRDATA (CYL, dpc_ucyl, 10, 8, DP_NUMDRV), PV_RZRO }, + { 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 (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_UNLOAD, UNIT_UNLOAD, "heads unloaded", "UNLOADED", dpc_load_unload }, - { UNIT_UNLOAD, 0, "heads loaded", "LOADED", dpc_load_unload }, - { 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 } }; + { UNIT_UNLOAD, UNIT_UNLOAD, "heads unloaded", "UNLOADED", dpc_load_unload }, + { UNIT_UNLOAD, 0, "heads loaded", "LOADED", dpc_load_unload }, + { 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, &dpc_detach, - &dpc_dib, DEV_DISABLE }; - -/* IOT routines */ + "DPC", dpc_unit, dpc_reg, dpc_mod, + DP_NUMDRV, 8, 24, 1, 8, 16, + NULL, NULL, &dpc_reset, + &dpc_boot, &dpc_attach, &dpc_detach, + &dpc_dib, DEV_DISABLE + }; + +/* IO instructions */ 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) { setFSR (devd); } /* STF */ - break; -case ioSFC: /* skip flag clear */ - if (FLG (devd) == 0) PC = (PC + 1) & VAMASK; - break; -case ioSFS: /* skip flag set */ - if (FLG (devd) != 0) PC = (PC + 1) & VAMASK; - break; -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) { clrFSR (devd); } /* H/C option */ +devd = IR & I_DEVMASK; /* get device no */ +switch (inst) { /* case on opcode */ + + case ioFLG: /* flag clear/set */ + if ((IR & I_HC) == 0) { setFSR (devd); } /* STF */ + break; + + case ioSFC: /* skip flag clear */ + if (FLG (devd) == 0) PC = (PC + 1) & VAMASK; + break; + + case ioSFS: /* skip flag set */ + if (FLG (devd) != 0) PC = (PC + 1) & VAMASK; + break; + + 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) { clrFSR (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) { setFSR (devc); } /* STF */ - break; -case ioSFC: /* skip flag clear */ - if (FLG (devc) == 0) PC = (PC + 1) & VAMASK; - break; -case ioSFS: /* skip flag set */ - if (FLG (devc) != 0) PC = (PC + 1) & VAMASK; - 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 ioOTX: /* output */ - dpc_obuf = dat; - if (!dp_ctype) break; - IR = IR | I_CTL; /* 13210 OTx causes CLC */ -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 */ - dpc_poll = 0; } /* clr cch poll */ - 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_SEEK: /* seek */ - dpc_poll = 1; /* enable polling */ - dp_god (fnc, drv, dpc_dtime); /* sched dch xfr */ - break; - case FNC_STA: /* rd sta */ - if (dp_ctype) { clrFSR (devd); } /* 13210? clr dch flag */ - case FNC_CHK: /* 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) { clrFSR (devc); } /* H/C option */ +devc = IR & I_DEVMASK; /* get device no */ +switch (inst) { /* case on opcode */ + + case ioFLG: /* flag clear/set */ + if ((IR & I_HC) == 0) { setFSR (devc); } /* STF */ + break; + + case ioSFC: /* skip flag clear */ + if (FLG (devc) == 0) PC = (PC + 1) & VAMASK; + break; + + case ioSFS: /* skip flag set */ + if (FLG (devc) != 0) PC = (PC + 1) & VAMASK; + 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 ioOTX: /* output */ + dpc_obuf = dat; + if (!dp_ctype) break; + IR = IR | I_CTL; /* 13210 OTx causes CLC */ + + 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 */ + dpc_poll = 0; /* clr cch poll */ + } + 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_SEEK: /* seek */ + dpc_poll = 1; /* enable polling */ + dp_god (fnc, drv, dpc_dtime); /* sched dch xfr */ + break; + + case FNC_STA: /* rd sta */ + if (dp_ctype) { clrFSR (devd); } /* 13210? clr dch flag */ + case FNC_CHK: /* 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 if */ + } /* end else */ + break; + + default: + break; + } + +if (IR & I_HC) { clrFSR (devc); } /* H/C option */ return dat; } - + /* Start data channel operation */ void dp_god (int32 fnc, int32 drv, int32 time) { -dpd_unit.DRV = drv; /* save unit */ -dpd_unit.FNC = fnc; /* save function */ +dpd_unit.DRV = drv; /* save unit */ +dpd_unit.FNC = fnc; /* save function */ sim_activate (&dpd_unit, time); return; } @@ -479,286 +513,316 @@ void dp_goc (int32 fnc, int32 drv, int32 time) { int32 t; -if (t = 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 + t; } /* include seek time */ -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 */ -dpc_sta[drv] = dpc_sta[drv] & ~STA_ATN; /* clear ATN */ -sim_activate (&dpc_unit[drv], time); /* activate unit */ +if (t = 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 + t; /* include seek time */ + } +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 */ +dpc_sta[drv] = dpc_sta[drv] & ~STA_ATN; /* clear ATN */ +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->DRV = target drive - uptr->FNC = target function + uptr->DRV = target drive + uptr->FNC = target function Seek substates - seek - transfer cylinder - seek1 - transfer head/surface + seek - transfer cylinder + seek1 - transfer head/surface Address record - ar - transfer cylinder - ar1 - transfer head/surface, finish operation - Status check - transfer status, finish operation + ar - transfer cylinder + ar1 - transfer head/surface, finish operation + Status check - transfer status, finish operation Check data - chk - transfer sector count + chk - transfer sector count */ t_stat dpd_svc (UNIT *uptr) { int32 i, drv, devc, devd, st; -drv = uptr->DRV; /* get drive no */ -devc = dpc_dib.devno; /* get cch devno */ -devd = dpd_dib.devno; /* get dch devno */ -switch (uptr->FNC) { /* case function */ +drv = uptr->DRV; /* get drive no */ +devc = dpc_dib.devno; /* get cch devno */ +devd = dpd_dib.devno; /* get dch devno */ +switch (uptr->FNC) { /* case function */ -case FNC_AR: /* arec, need cyl */ -case FNC_SEEK: /* seek, need cyl */ - if (CMD (devd)) { /* dch active? */ - dpc_rarc = DA_GETCYL (dpd_obuf); /* set RAR from cyl word */ - dpd_wval = 0; /* clr data valid */ - setFSR (devd); /* set dch flg */ - clrCMD (devd); /* clr dch cmd */ - if (uptr->FNC == FNC_AR) uptr->FNC = FNC_AR1; - else uptr->FNC = FNC_SEEK1; } /* advance state */ - sim_activate (uptr, dpc_xtime); /* no, wait more */ - break; + case FNC_AR: /* arec, need cyl */ + case FNC_SEEK: /* seek, need cyl */ + if (CMD (devd)) { /* dch active? */ + dpc_rarc = DA_GETCYL (dpd_obuf); /* set RAR from cyl word */ + dpd_wval = 0; /* clr data valid */ + setFSR (devd); /* set dch flg */ + clrCMD (devd); /* clr dch cmd */ + if (uptr->FNC == FNC_AR) uptr->FNC = FNC_AR1; + else uptr->FNC = FNC_SEEK1; /* advance state */ + } + sim_activate (uptr, dpc_xtime); /* no, wait more */ + break; -case FNC_AR1: /* arec, need hd/sec */ -case FNC_SEEK1: /* seek, need hd/sec */ - if (CMD (devd)) { /* dch active? */ - dpc_rarh = DA_GETHD (dpd_obuf); /* set RAR from head */ - dpc_rars = DA_GETSC (dpd_obuf); /* set RAR from sector */ - dpd_wval = 0; /* clr data valid */ - setFSR (devd); /* set dch flg */ - clrCMD (devd); /* clr dch cmd */ - if (uptr->FNC == FNC_AR1) { - setFSR (devc); /* set cch flg */ - clrCMD (devc); /* clr cch cmd */ - dpc_sta[drv] = dpc_sta[drv] | STA_ATN; /* set drv attn */ - break; } /* done if Address Record */ - if (sim_is_active (&dpc_unit[drv])) { /* if busy, */ - dpc_sta[drv] = dpc_sta[drv] | STA_SKE; /* seek check */ - break; } /* allow prev seek to cmpl */ - if ((dpc_rarc >= DP_NUMCY) || /* invalid cyl? */ - (dp_ctype && (dpc_rars >= DP_NUMSC3))) { /* invalid sector? (13210A) */ - dpc_sta[drv] = dpc_sta[drv] | STA_SKE; /* seek check */ - sim_activate (&dpc_unit[drv], 1); /* schedule drive no-wait */ - dpc_unit[drv].FNC = FNC_SEEK3; /* do immed compl w/poll */ - break; } - st = abs (dpc_rarc - dpc_ucyl[drv]) * dpc_stime; - if (st == 0) st = dpc_stime; /* min time */ - dpc_ucyl[drv] = dpc_rarc; /* transfer RAR */ - 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].FNC = FNC_SEEK2; } /* set operation */ - else sim_activate (uptr, dpc_xtime); /* no, wait more */ - break; + case FNC_AR1: /* arec, need hd/sec */ + case FNC_SEEK1: /* seek, need hd/sec */ + if (CMD (devd)) { /* dch active? */ + dpc_rarh = DA_GETHD (dpd_obuf); /* set RAR from head */ + dpc_rars = DA_GETSC (dpd_obuf); /* set RAR from sector */ + dpd_wval = 0; /* clr data valid */ + setFSR (devd); /* set dch flg */ + clrCMD (devd); /* clr dch cmd */ + if (uptr->FNC == FNC_AR1) { + setFSR (devc); /* set cch flg */ + clrCMD (devc); /* clr cch cmd */ + dpc_sta[drv] = dpc_sta[drv] | STA_ATN; /* set drv attn */ + break; /* done if Address Record */ + } + if (sim_is_active (&dpc_unit[drv])) { /* if busy, */ + dpc_sta[drv] = dpc_sta[drv] | STA_SKE; /* seek check */ + break; /* allow prev seek to cmpl */ + } + if ((dpc_rarc >= DP_NUMCY) || /* invalid cyl? */ + (dp_ctype && (dpc_rars >= DP_NUMSC3))) { /* invalid sector? (13210A) */ + dpc_sta[drv] = dpc_sta[drv] | STA_SKE; /* seek check */ + sim_activate (&dpc_unit[drv], 1); /* schedule drive no-wait */ + dpc_unit[drv].FNC = FNC_SEEK3; /* do immed compl w/poll */ + break; + } + st = abs (dpc_rarc - dpc_ucyl[drv]) * dpc_stime; + if (st == 0) st = dpc_stime; /* min time */ + dpc_ucyl[drv] = dpc_rarc; /* transfer RAR */ + 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].FNC = FNC_SEEK2; /* set operation */ + } + 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_UNLOAD) == 0) { /* drive up? */ - dpd_ibuf = dpc_sta[drv] & ~STA_ERR; /* clear err */ - if (dp_ctype) dpd_ibuf = /* 13210? */ - (dpd_ibuf & ~(STA_MBZ13 | STA_PROT)) | - (dpc_unit[drv].flags & UNIT_WPRT? STA_PROT: 0); } - else dpd_ibuf = STA_UNLOADED; /* not ready */ - if (dpd_ibuf & STA_ANYERR) /* errors? set flg */ - dpd_ibuf = dpd_ibuf | STA_ERR; - setFSR (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); - dpc_poll = 1; /* enable polling */ - for (i = 0; i < DP_NUMDRV; i++) { /* loop thru drives */ - if (dpc_sta[i] & STA_ATN) { /* any ATN set? */ - setFSR (devc); /* set cch flg */ - break; } } - break; + case FNC_STA: /* read status */ + if (CMD (devd) || dp_ctype) { /* dch act or 13210? */ + if ((dpc_unit[drv].flags & UNIT_UNLOAD) == 0) { /* drive up? */ + dpd_ibuf = dpc_sta[drv] & ~STA_ERR; /* clear err */ + if (dp_ctype) dpd_ibuf = /* 13210? */ + (dpd_ibuf & ~(STA_MBZ13 | STA_PROT)) | + (dpc_unit[drv].flags & UNIT_WPRT? STA_PROT: 0); + } + else dpd_ibuf = STA_UNLOADED; /* not ready */ + if (dpd_ibuf & STA_ANYERR) /* errors? set flg */ + dpd_ibuf = dpd_ibuf | STA_ERR; + setFSR (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); + dpc_poll = 1; /* enable polling */ + for (i = 0; i < DP_NUMDRV; i++) { /* loop thru drives */ + if (dpc_sta[i] & STA_ATN) { /* any ATN set? */ + setFSR (devc); /* set cch flg */ + break; + } + } + 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 */ - dp_goc (FNC_CHK1, drv, dpc_xtime); } /* sched drv */ - 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 */ + dp_goc (FNC_CHK1, drv, dpc_xtime); /* sched drv */ + } + else sim_activate (uptr, dpc_xtime); /* wait more */ + break; -default: - return SCPE_IERR; } + 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 + seek2 - done + Refine sector - erase sector, finish operation Check data - chk1 - finish operation + chk1 - finish operation Read Write */ #define GETDA(x,y,z) \ - (((((x) * DP_NUMSF) + (y)) * DP_NUMSC) + (z)) * DP_NUMWD + (((((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_UNLOAD) { /* drive down? */ - setFSR (devc); /* set cch flg */ - clrCMD (devc); /* clr cch cmd */ - dpc_sta[drv] = 0; /* clr status */ - dpc_busy = 0; /* ctlr is free */ - dpc_poll = 0; /* polling disabled */ - dpd_xfer = 0; - dpd_wval = 0; - return SCPE_OK; } -switch (uptr->FNC) { /* case function */ +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_UNLOAD) { /* drive down? */ + setFSR (devc); /* set cch flg */ + clrCMD (devc); /* clr cch cmd */ + dpc_sta[drv] = 0; /* clr status */ + dpc_busy = 0; /* ctlr is free */ + dpc_poll = 0; /* polling disabled */ + dpd_xfer = 0; + dpd_wval = 0; + return SCPE_OK; + } +switch (uptr->FNC) { /* case function */ -case FNC_SEEK2: /* positioning done */ - dpc_sta[drv] = (dpc_sta[drv] | STA_ATN) & ~STA_BSY; /* fall into cmpl */ + case FNC_SEEK2: /* positioning done */ + dpc_sta[drv] = (dpc_sta[drv] | STA_ATN) & ~STA_BSY; /* fall into cmpl */ + case FNC_SEEK3: /* seek complete */ + if (dpc_poll) { /* polling enabled? */ + setFSR (devc); /* set cch flg */ + clrCMD (devc); /* clear cmd */ + } + return SCPE_OK; -case FNC_SEEK3: /* seek complete */ - if (dpc_poll) { /* polling enabled? */ - setFSR (devc); /* set cch flg */ - clrCMD (devc); } /* clear cmd */ - return SCPE_OK; + case FNC_REF: /* refine sector */ + break; /* just a NOP */ -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 (dpc_rarc != dpc_ucyl[drv]) /* RAR cyl miscompare? */ - dpc_sta[drv] = dpc_sta[drv] | STA_AER; /* set flag, read */ - if (dpc_rars >= 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, dpc_rarh, dpc_rars); /* calc disk addr */ - dpc_rars = (dpc_rars + 1) % DP_NUMSC; /* incr sector */ - if (dpc_rars == 0) { /* wrap? */ - dpc_rarh = dpc_rarh ^ 1; /* incr head */ - dpc_eoc = ((dpc_rarh & 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? */ - setFSR (devd); } /* set flag */ - clrCMD (devd); /* clr dch cmd */ - sim_activate (uptr, dpc_xtime); /* sched next word */ - return SCPE_OK; + case FNC_RD: /* read */ + case FNC_CHK1: /* check */ + if (dp_ptr == 0) { /* new sector? */ + if (!CMD (devd) && (uptr->FNC != FNC_CHK1)) break; + if (dpc_rarc != dpc_ucyl[drv]) /* RAR cyl miscompare? */ + dpc_sta[drv] = dpc_sta[drv] | STA_AER; /* set flag, read */ + if (dpc_rars >= 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, dpc_rarh, dpc_rars); /* calc disk addr */ + dpc_rars = (dpc_rars + 1) % DP_NUMSC; /* incr sector */ + if (dpc_rars == 0) { /* wrap? */ + dpc_rarh = dpc_rarh ^ 1; /* incr head */ + dpc_eoc = ((dpc_rarh & 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? */ + setFSR (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 ((dpc_rarc != dpc_ucyl[drv]) || /* RAR cyl miscompare? */ - (dpc_rars >= DP_NUMSC)) { /* bad sector? */ - dpc_sta[drv] = dpc_sta[drv] | STA_AER; /* address error */ - 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, dpc_rarh, dpc_rars); /* calc disk addr */ - dpc_rars = (dpc_rars + 1) % DP_NUMSC; /* incr sector */ - if (dpc_rars == 0) { /* wrap? */ - dpc_rarh = dpc_rarh ^ 1; /* incr head */ - dpc_eoc = ((dpc_rarh & 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? */ - setFSR (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 ((dpc_rarc != dpc_ucyl[drv]) || /* RAR cyl miscompare? */ + (dpc_rars >= DP_NUMSC)) { /* bad sector? */ + dpc_sta[drv] = dpc_sta[drv] | STA_AER; /* address error */ + 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, dpc_rarh, dpc_rars); /* calc disk addr */ + dpc_rars = (dpc_rars + 1) % DP_NUMSC; /* incr sector */ + if (dpc_rars == 0) { /* wrap? */ + dpc_rarh = dpc_rarh ^ 1; /* incr head */ + dpc_eoc = ((dpc_rarh & 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? */ + setFSR (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 */ + default: + return SCPE_IERR; + } /* end case fnc */ -dpc_sta[drv] = dpc_sta[drv] | STA_ATN; /* set ATN */ -setFSR (devc); /* set cch flg */ -clrCMD (devc); /* clr cch cmd */ -dpc_busy = 0; /* ctlr is free */ +dpc_sta[drv] = dpc_sta[drv] | STA_ATN; /* set ATN */ +setFSR (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; } +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 drv; -hp_enbdis_pair (dptr, /* make pair cons */ - (dptr == &dpd_dev)? &dpc_dev: &dpd_dev); -dpd_ibuf = dpd_obuf = 0; /* clear buffers */ +hp_enbdis_pair (dptr, /* make pair cons */ + (dptr == &dpd_dev)? &dpc_dev: &dpd_dev); +dpd_ibuf = dpd_obuf = 0; /* clear buffers */ dpc_busy = dpc_obuf = 0; dpc_eoc = 0; dpc_poll = 0; dpd_xfer = dpd_wval = 0; dp_ptr = 0; -dpc_rarc = dpc_rarh = dpc_rars = 0; /* clear RAR */ -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 */ -dpc_dib.srq = dpd_dib.flg = 1; /* srq follows flg */ -sim_cancel (&dpd_unit); /* cancel dch */ -for (drv = 0; drv < DP_NUMDRV; drv++) { /* loop thru drives */ - sim_cancel (&dpc_unit[drv]); /* cancel activity */ - dpc_unit[drv].FNC = 0; /* clear function */ - dpc_ucyl[drv] = 0; /* clear drive pos */ - if (dpc_unit[drv].flags & UNIT_ATT) - dpc_sta[drv] = dpc_sta[drv] & STA_1ST; /* first seek status */ - else dpc_sta[drv] = 0; } /* clear status */ +dpc_rarc = dpc_rarh = dpc_rars = 0; /* clear RAR */ +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 */ +dpc_dib.srq = dpd_dib.flg = 1; /* srq follows flg */ +sim_cancel (&dpd_unit); /* cancel dch */ +for (drv = 0; drv < DP_NUMDRV; drv++) { /* loop thru drives */ + sim_cancel (&dpc_unit[drv]); /* cancel activity */ + dpc_unit[drv].FNC = 0; /* clear function */ + dpc_ucyl[drv] = 0; /* clear drive pos */ + if (dpc_unit[drv].flags & UNIT_ATT) + dpc_sta[drv] = dpc_sta[drv] & STA_1ST; /* first seek status */ + else dpc_sta[drv] = 0; /* clear status */ + } return SCPE_OK; } @@ -768,7 +832,7 @@ t_stat dpc_attach (UNIT *uptr, char *cptr) { t_stat r; -r = attach_unit (uptr, cptr); /* attach unit */ +r = attach_unit (uptr, cptr); /* attach unit */ if (r == SCPE_OK) dpc_load_unload (uptr, 0, NULL, NULL);/* if OK, load heads */ return r; } @@ -777,8 +841,8 @@ return r; t_stat dpc_detach (UNIT* uptr) { -dpc_load_unload (uptr, UNIT_UNLOAD, NULL, NULL); /* unload heads */ -return detach_unit (uptr); /* detach unit */ +dpc_load_unload (uptr, UNIT_UNLOAD, NULL, NULL); /* unload heads */ +return detach_unit (uptr); /* detach unit */ } /* Load and unload heads */ @@ -787,18 +851,20 @@ t_stat dpc_load_unload (UNIT *uptr, int32 value, char *cptr, void *desc) { uint32 drv; -if ((uptr->flags & UNIT_ATT) == 0) return SCPE_UNATT; /* must be attached to load */ +if ((uptr->flags & UNIT_ATT) == 0) return SCPE_UNATT; /* must be attached to load */ -if (value == UNIT_UNLOAD) /* unload heads? */ - uptr->flags = uptr->flags | UNIT_UNLOAD; /* indicate unload */ -else { /* load heads */ - uptr->flags = uptr->flags & ~UNIT_UNLOAD; /* indicate load */ - drv = uptr - dpc_dev.units; /* get drive no */ - dpc_sta[drv] = dpc_sta[drv] | STA_ATN | STA_1ST;/* update status */ - if (dpc_poll) { /* polling enabled? */ - dpc_dib.fbf = 1; /* set fbf */ - dpc_dib.flg = 1; /* set flg */ - dpc_dib.srq = 1; } } /* srq follows flg */ +if (value == UNIT_UNLOAD) /* unload heads? */ + uptr->flags = uptr->flags | UNIT_UNLOAD; /* indicate unload */ +else { /* load heads */ + uptr->flags = uptr->flags & ~UNIT_UNLOAD; /* indicate load */ + drv = uptr - dpc_dev.units; /* get drive no */ + dpc_sta[drv] = dpc_sta[drv] | STA_ATN | STA_1ST; /* update status */ + if (dpc_poll) { /* polling enabled? */ + dpc_dib.fbf = 1; /* set fbf */ + dpc_dib.flg = 1; /* set flg */ + dpc_dib.srq = 1; /* srq follows flg */ + } + } return SCPE_OK; } @@ -810,9 +876,10 @@ 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; } + 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); + dpc_unit[i].capac = (val? DP_SIZE3: DP_SIZE2); dp_ctype = val; return SCPE_OK; } @@ -829,76 +896,77 @@ return SCPE_OK; /* 7900/7901 bootstrap routine (HP 12992F ROM) */ const uint16 dp_rom[IBL_LNT] = { - 0106710, /*ST CLC DC ; clr dch */ - 0106711, /* CLC CC ; clr cch */ - 0017757, /* JSB STAT ; get status */ - 0067746, /*SK LDB SKCMD ; seek cmd */ - 0106610, /* OTB DC ; cyl # */ - 0103710, /* STC DC,C ; to dch */ - 0106611, /* OTB CC ; seek cmd */ - 0103711, /* STC CC,C ; to cch */ - 0102310, /* 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 = removable */ - 0106610, /* OTB DC ; head/sector */ - 0103710, /* STC DC,C ; to dch */ - 0102311, /* 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 */ - 0102611, /* OTA CC ; to cch */ - 0103710, /* STC DC,C ; start dch */ - 0103706, /* STC 6,C ; start DMA */ - 0103711, /* STC CC,C ; start cch */ - 0102311, /* 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 */ - 0102611, /* OTC CC ; to cch */ - 0103711, /* STC CC,C ; start cch */ - 0102310, /* SFS DC ; done? */ - 0027763, /* JMP *-1 */ - 0102510, /* 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 */ - 0120010, /*DMACW 120000+DC */ - 0000000 }; /* -ST */ + 0106710, /*ST CLC DC ; clr dch */ + 0106711, /* CLC CC ; clr cch */ + 0017757, /* JSB STAT ; get status */ + 0067746, /*SK LDB SKCMD ; seek cmd */ + 0106610, /* OTB DC ; cyl # */ + 0103710, /* STC DC,C ; to dch */ + 0106611, /* OTB CC ; seek cmd */ + 0103711, /* STC CC,C ; to cch */ + 0102310, /* 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 = removable */ + 0106610, /* OTB DC ; head/sector */ + 0103710, /* STC DC,C ; to dch */ + 0102311, /* 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 */ + 0102611, /* OTA CC ; to cch */ + 0103710, /* STC DC,C ; start dch */ + 0103706, /* STC 6,C ; start DMA */ + 0103711, /* STC CC,C ; start cch */ + 0102311, /* 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 */ + 0102611, /* OTC CC ; to cch */ + 0103711, /* STC CC,C ; start cch */ + 0102310, /* SFS DC ; done? */ + 0027763, /* JMP *-1 */ + 0102510, /* 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 */ + 0120010, /*DMACW 120000+DC */ + 0000000 /* -ST */ + }; t_stat dpc_boot (int32 unitno, DEVICE *dptr) { int32 dev; -if (unitno != 0) return SCPE_NOFNC; /* only unit 0 */ -dev = dpd_dib.devno; /* get data chan dev */ -if (ibl_copy (dp_rom, dev)) return SCPE_IERR; /* copy boot to memory */ -SR = (SR & IBL_OPT) | IBL_DP | (dev << IBL_V_DEV); /* set SR */ -if (sim_switches & SWMASK ('R')) SR = SR | IBL_DP_REM; /* boot from removable? */ +if (unitno != 0) return SCPE_NOFNC; /* only unit 0 */ +dev = dpd_dib.devno; /* get data chan dev */ +if (ibl_copy (dp_rom, dev)) return SCPE_IERR; /* copy boot to memory */ +SR = (SR & IBL_OPT) | IBL_DP | (dev << IBL_V_DEV); /* set SR */ +if (sim_switches & SWMASK ('R')) SR = SR | IBL_DP_REM; /* boot from removable? */ return SCPE_OK; } diff --git a/HP2100/hp2100_dq.c b/HP2100/hp2100_dq.c index 4da7b3d6..a0b23ddc 100644 --- a/HP2100/hp2100_dq.c +++ b/HP2100/hp2100_dq.c @@ -1,6 +1,6 @@ /* hp2100_dq.c: HP 2100 12565A disk simulator - Copyright (c) 1993-2004, Bill McDermith + Copyright (c) 1993-2005, Bill McDermith Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -19,25 +19,25 @@ 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 + 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 + dq 12565A 2883 disk system - 01-Mar-05 JDB Added SET UNLOAD/LOAD - 07-Oct-04 JDB Fixed enable/disable from either device - Shortened xtime from 5 to 3 (drive avg 156KW/second) - Fixed not ready/any error status - Fixed RAR model - 21-Apr-04 RMS Fixed typo in boot loader (found by Dave Bryan) - 26-Apr-04 RMS Fixed SFS x,C and SFC x,C - Fixed SR setting in IBL - Revised IBL loader - Implemented DMA SRQ (follows FLG) - 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 + 01-Mar-05 JDB Added SET UNLOAD/LOAD + 07-Oct-04 JDB Fixed enable/disable from either device + Shortened xtime from 5 to 3 (drive avg 156KW/second) + Fixed not ready/any error status + Fixed RAR model + 21-Apr-04 RMS Fixed typo in boot loader (found by Dave Bryan) + 26-Apr-04 RMS Fixed SFS x,C and SFC x,C + Fixed SR setting in IBL + Revised IBL loader + Implemented DMA SRQ (follows FLG) + 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 @@ -71,97 +71,97 @@ #include "hp2100_defs.h" -#define UNIT_V_WLK (UNIT_V_UF + 0) /* write locked */ -#define UNIT_V_UNLOAD (UNIT_V_UF + 1) /* heads unloaded */ -#define UNIT_WLK (1 << UNIT_V_WLK) -#define UNIT_UNLOAD (1 << UNIT_V_UNLOAD) -#define FNC u3 /* saved function */ -#define DRV u4 /* drive number (DC) */ -#define UNIT_WPRT (UNIT_WLK | UNIT_RO) /* write prot */ +#define UNIT_V_WLK (UNIT_V_UF + 0) /* write locked */ +#define UNIT_V_UNLOAD (UNIT_V_UF + 1) /* heads unloaded */ +#define UNIT_WLK (1 << UNIT_V_WLK) +#define UNIT_UNLOAD (1 << UNIT_V_UNLOAD) +#define FNC u3 /* saved function */ +#define DRV u4 /* drive number (DC) */ +#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 */ +#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 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 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) +#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 */ +#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_ANYERR (STA_NRDY | STA_EOC | STA_AER | STA_FLG | STA_DTE) - +#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_ANYERR (STA_NRDY | STA_EOC | STA_AER | STA_FLG | STA_DTE) + extern uint32 PC, SR; extern uint32 dev_cmd[2], dev_ctl[2], dev_flg[2], dev_fbf[2], dev_srq[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 = 3; /* 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 = 0; /* RAR cylinder */ -uint8 dqc_rarh = 0; /* RAR head */ -uint8 dqc_rars = 0; /* RAR sector */ -uint8 dqc_ucyl[DQ_NUMDRV] = { 0 }; /* unit cylinder */ -uint8 dqc_uhed[DQ_NUMDRV] = { 0 }; /* unit head */ -uint16 dqc_sta[DQ_NUMDRV] = { 0 }; /* unit status */ -uint16 dqxb[DQ_NUMWD]; /* sector buffer */ +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 = 3; /* 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 = 0; /* RAR cylinder */ +uint8 dqc_rarh = 0; /* RAR head */ +uint8 dqc_rars = 0; /* RAR sector */ +uint8 dqc_ucyl[DQ_NUMDRV] = { 0 }; /* unit cylinder */ +uint8 dqc_uhed[DQ_NUMDRV] = { 0 }; /* unit head */ +uint16 dqc_sta[DQ_NUMDRV] = { 0 }; /* unit status */ +uint16 dqxb[DQ_NUMWD]; /* sector buffer */ DEVICE dqd_dev, dqc_dev; int32 dqdio (int32 inst, int32 IR, int32 dat); @@ -175,17 +175,18 @@ t_stat dqc_load_unload (UNIT *uptr, int32 value, char *cptr, void *desc); 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 + dqd_dev DQD device descriptor + dqd_unit DQD unit list + dqd_reg DQD register list */ DIB dq_dib[] = { - { DQD, 0, 0, 0, 0, 0, &dqdio }, - { DQC, 0, 0, 0, 0, 0, &dqcio } }; + { DQD, 0, 0, 0, 0, 0, &dqdio }, + { DQC, 0, 0, 0, 0, 0, &dqcio } + }; #define dqd_dib dq_dib[0] #define dqc_dib dq_dib[1] @@ -193,193 +194,223 @@ DIB dq_dib[] = { UNIT dqd_unit = { UDATA (&dqd_svc, 0, 0) }; REG dqd_reg[] = { - { ORDATA (IBUF, dqd_ibuf, 16) }, - { ORDATA (OBUF, dqd_obuf, 16) }, - { BRDATA (DBUF, dqxb, 8, 16, DQ_NUMWD) }, - { DRDATA (BPTR, dq_ptr, DQ_N_NUMWD) }, - { 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 (SRQ, dqd_dib.srq, 0) }, - { FLDATA (XFER, dqd_xfer, 0) }, - { FLDATA (WVAL, dqd_wval, 0) }, - { ORDATA (DEVNO, dqd_dib.devno, 6), REG_HRO }, - { NULL } }; + { ORDATA (IBUF, dqd_ibuf, 16) }, + { ORDATA (OBUF, dqd_obuf, 16) }, + { BRDATA (DBUF, dqxb, 8, 16, DQ_NUMWD) }, + { DRDATA (BPTR, dq_ptr, DQ_N_NUMWD) }, + { 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 (SRQ, dqd_dib.srq, 0) }, + { FLDATA (XFER, dqd_xfer, 0) }, + { FLDATA (WVAL, dqd_wval, 0) }, + { 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 } }; + { 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, DEV_DISABLE }; + "DQD", &dqd_unit, dqd_reg, dqd_mod, + 1, 10, DQ_N_NUMWD, 1, 8, 16, + NULL, NULL, &dqc_reset, + NULL, NULL, NULL, + &dqd_dib, DEV_DISABLE + }; /* DQC data structures - dqc_dev DQC device descriptor - dqc_unit DQC unit list - dqc_reg DQC register list - dqc_mod DQC modifier list + 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_ROABLE | - UNIT_DISABLE | UNIT_UNLOAD, DQ_SIZE) }, - { UDATA (&dqc_svc, UNIT_FIX | UNIT_ATTABLE | UNIT_ROABLE | - UNIT_DISABLE | UNIT_UNLOAD, DQ_SIZE) } }; + { UDATA (&dqc_svc, UNIT_FIX | UNIT_ATTABLE | UNIT_ROABLE | + UNIT_DISABLE | UNIT_UNLOAD, DQ_SIZE) }, + { UDATA (&dqc_svc, UNIT_FIX | UNIT_ATTABLE | UNIT_ROABLE | + UNIT_DISABLE | UNIT_UNLOAD, 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) }, - { FLDATA (SRQ, dqc_dib.srq, 0) }, - { DRDATA (RARC, dqc_rarc, 8), PV_RZRO }, - { DRDATA (RARH, dqc_rarh, 5), PV_RZRO }, - { DRDATA (RARS, dqc_rars, 5), PV_RZRO }, - { BRDATA (CYL, dqc_ucyl, 10, 8, DQ_NUMDRV), PV_RZRO }, - { BRDATA (HED, dqc_uhed, 10, 5, DQ_NUMDRV), PV_RZRO }, - { 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 (UFNC, dqc_unit[0].FNC, 8, 8, 0, - DQ_NUMDRV, REG_HRO) }, - { ORDATA (DEVNO, dqc_dib.devno, 6), REG_HRO }, - { NULL } }; + { 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) }, + { FLDATA (SRQ, dqc_dib.srq, 0) }, + { DRDATA (RARC, dqc_rarc, 8), PV_RZRO }, + { DRDATA (RARH, dqc_rarh, 5), PV_RZRO }, + { DRDATA (RARS, dqc_rars, 5), PV_RZRO }, + { BRDATA (CYL, dqc_ucyl, 10, 8, DQ_NUMDRV), PV_RZRO }, + { BRDATA (HED, dqc_uhed, 10, 5, DQ_NUMDRV), PV_RZRO }, + { 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 (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_UNLOAD, UNIT_UNLOAD, "heads unloaded", "UNLOADED", dqc_load_unload }, - { UNIT_UNLOAD, 0, "heads loaded", "LOADED", dqc_load_unload }, - { 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 } }; + { UNIT_UNLOAD, UNIT_UNLOAD, "heads unloaded", "UNLOADED", dqc_load_unload }, + { UNIT_UNLOAD, 0, "heads loaded", "LOADED", dqc_load_unload }, + { 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, &dqc_attach, &dqc_detach, - &dqc_dib, DEV_DISABLE }; - -/* IOT routines */ + "DQC", dqc_unit, dqc_reg, dqc_mod, + DQ_NUMDRV, 8, 24, 1, 8, 16, + NULL, NULL, &dqc_reset, + &dqc_boot, &dqc_attach, &dqc_detach, + &dqc_dib, DEV_DISABLE + }; + +/* IO instructions */ 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) { setFSR (devd); } /* STF */ - break; -case ioSFC: /* skip flag clear */ - if (FLG (devd) == 0) PC = (PC + 1) & VAMASK; - break; -case ioSFS: /* skip flag set */ - if (FLG (devd) != 0) PC = (PC + 1) & VAMASK; - break; -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; } - break; -default: - break; } -if (IR & I_HC) { clrFSR (devd); } /* H/C option */ +devd = IR & I_DEVMASK; /* get device no */ +switch (inst) { /* case on opcode */ + + case ioFLG: /* flag clear/set */ + if ((IR & I_HC) == 0) { setFSR (devd); } /* STF */ + break; + + case ioSFC: /* skip flag clear */ + if (FLG (devd) == 0) PC = (PC + 1) & VAMASK; + break; + + case ioSFS: /* skip flag set */ + if (FLG (devd) != 0) PC = (PC + 1) & VAMASK; + break; + + 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; + } + break; + + default: + break; + } + +if (IR & I_HC) { clrFSR (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) { setFSR (devc); } /* STF */ - break; -case ioSFC: /* skip flag clear */ - if (FLG (devc) == 0) PC = (PC + 1) & VAMASK; - break; -case ioSFS: /* skip flag set */ - if (FLG (devc) != 0) PC = (PC + 1) & VAMASK; - break; -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) { clrFSR (devc); } /* H/C option */ +devc = IR & I_DEVMASK; /* get device no */ +switch (inst) { /* case on opcode */ + + case ioFLG: /* flag clear/set */ + if ((IR & I_HC) == 0) { setFSR (devc); } /* STF */ + break; + + case ioSFC: /* skip flag clear */ + if (FLG (devc) == 0) PC = (PC + 1) & VAMASK; + break; + + case ioSFS: /* skip flag set */ + if (FLG (devc) != 0) PC = (PC + 1) & VAMASK; + break; + + 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) { clrFSR (devc); } /* H/C option */ return dat; } - + /* Start data channel operation */ void dq_god (int32 fnc, int32 drv, int32 time) { -dqd_unit.DRV = drv; /* save unit */ -dqd_unit.FNC = fnc; /* save function */ +dqd_unit.DRV = drv; /* save unit */ +dqd_unit.FNC = fnc; /* save function */ sim_activate (&dqd_unit, time); return; } @@ -390,133 +421,140 @@ void dq_goc (int32 fnc, int32 drv, int32 time) { int32 t; -if (t = sim_is_active (&dqc_unit[drv])) { /* still seeking? */ - sim_cancel (&dqc_unit[drv]); /* cancel */ - time = time + t; } /* include seek time */ -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 */ +if (t = sim_is_active (&dqc_unit[drv])) { /* still seeking? */ + sim_cancel (&dqc_unit[drv]); /* cancel */ + time = time + t; /* include seek time */ + } +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->DRV = target drive - uptr->FNC = target function + uptr->DRV = target drive + uptr->FNC = target function Seek substates - seek - transfer cylinder - seek1 - transfer head/surface, sched drive + seek - transfer cylinder + seek1 - transfer head/surface, sched drive Recalibrate substates - rcl - clear cyl/head/surface, sched drive + rcl - clear cyl/head/surface, sched drive Load address - la - transfer cylinder - la1 - transfer head/surface, finish operation - Status check - transfer status, finish operation + la - transfer cylinder + la1 - transfer head/surface, finish operation + Status check - transfer status, finish operation Check data - chk - transfer sector count, sched drive + chk - transfer sector count, sched drive */ t_stat dqd_svc (UNIT *uptr) { int32 drv, devc, devd, st; -drv = uptr->DRV; /* get drive no */ -devc = dqc_dib.devno; /* get cch devno */ -devd = dqd_dib.devno; /* get dch devno */ -switch (uptr->FNC) { /* case function */ +drv = uptr->DRV; /* get drive no */ +devc = dqc_dib.devno; /* get cch devno */ +devd = dqd_dib.devno; /* get dch devno */ +switch (uptr->FNC) { /* case function */ -case FNC_LA: /* arec, need cyl */ -case FNC_SEEK: /* seek, need cyl */ - if (CMD (devd)) { /* dch active? */ - dqc_rarc = DA_GETCYL (dqd_obuf); /* set RAR from cyl word */ - dqd_wval = 0; /* clr data valid */ - setFSR (devd); /* set dch flg */ - clrCMD (devd); /* clr dch cmd */ - if (uptr->FNC == FNC_LA) uptr->FNC = FNC_LA1; - else uptr->FNC = FNC_SEEK1; } /* advance state */ - sim_activate (uptr, dqc_xtime); /* no, wait more */ - break; + case FNC_LA: /* arec, need cyl */ + case FNC_SEEK: /* seek, need cyl */ + if (CMD (devd)) { /* dch active? */ + dqc_rarc = DA_GETCYL (dqd_obuf); /* set RAR from cyl word */ + dqd_wval = 0; /* clr data valid */ + setFSR (devd); /* set dch flg */ + clrCMD (devd); /* clr dch cmd */ + if (uptr->FNC == FNC_LA) uptr->FNC = FNC_LA1; + else uptr->FNC = FNC_SEEK1; /* advance state */ + } + sim_activate (uptr, dqc_xtime); /* no, wait more */ + break; -case FNC_LA1: /* arec, need hd/sec */ -case FNC_SEEK1: /* seek, need hd/sec */ - if (CMD (devd)) { /* dch active? */ - dqc_rarh = DA_GETHD (dqd_obuf); /* set RAR from head */ - dqc_rars = DA_GETSC (dqd_obuf); /* set RAR from sector */ - dqd_wval = 0; /* clr data valid */ - setFSR (devd); /* set dch flg */ - clrCMD (devd); /* clr dch cmd */ - if (uptr->FNC == FNC_LA1) { - setFSR (devc); /* set cch flg */ - clrCMD (devc); /* clr cch cmd */ - break; } /* done if Load Address */ - if (sim_is_active (&dqc_unit[drv])) break; /* if busy, seek check */ - st = abs (dqc_rarc - dqc_ucyl[drv]) * dqc_stime; - if (st == 0) st = dqc_xtime; /* if on cyl, min time */ - else dqc_sta[drv] = dqc_sta[drv] | STA_BSY; /* set busy */ - dqc_ucyl[drv] = dqc_rarc; /* transfer RAR */ - dqc_uhed[drv] = dqc_rarh; - sim_activate (&dqc_unit[drv], st); /* schedule op */ - dqc_unit[drv].FNC = FNC_SEEK2; } /* advance state */ - else sim_activate (uptr, dqc_xtime); /* no, wait more */ - break; + case FNC_LA1: /* arec, need hd/sec */ + case FNC_SEEK1: /* seek, need hd/sec */ + if (CMD (devd)) { /* dch active? */ + dqc_rarh = DA_GETHD (dqd_obuf); /* set RAR from head */ + dqc_rars = DA_GETSC (dqd_obuf); /* set RAR from sector */ + dqd_wval = 0; /* clr data valid */ + setFSR (devd); /* set dch flg */ + clrCMD (devd); /* clr dch cmd */ + if (uptr->FNC == FNC_LA1) { + setFSR (devc); /* set cch flg */ + clrCMD (devc); /* clr cch cmd */ + break; /* done if Load Address */ + } + if (sim_is_active (&dqc_unit[drv])) break; /* if busy, seek check */ + st = abs (dqc_rarc - dqc_ucyl[drv]) * dqc_stime; + if (st == 0) st = dqc_xtime; /* if on cyl, min time */ + else dqc_sta[drv] = dqc_sta[drv] | STA_BSY; /* set busy */ + dqc_ucyl[drv] = dqc_rarc; /* transfer RAR */ + dqc_uhed[drv] = dqc_rarh; + sim_activate (&dqc_unit[drv], st); /* schedule op */ + dqc_unit[drv].FNC = FNC_SEEK2; /* advance state */ + } + else sim_activate (uptr, dqc_xtime); /* no, wait more */ + break; -case FNC_RCL: /* recalibrate */ - dqc_rarc = dqc_rarh = dqc_rars = 0; /* clear RAR */ - if (sim_is_active (&dqc_unit[drv])) break; /* ignore if busy */ - st = dqc_ucyl[drv] * 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_ucyl[drv] = dqc_uhed[drv] = 0; /* clear drive pos */ - dqc_unit[drv].FNC = FNC_SEEK2; /* advance state */ - break; + case FNC_RCL: /* recalibrate */ + dqc_rarc = dqc_rarh = dqc_rars = 0; /* clear RAR */ + if (sim_is_active (&dqc_unit[drv])) break; /* ignore if busy */ + st = dqc_ucyl[drv] * 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_ucyl[drv] = dqc_uhed[drv] = 0; /* clear drive pos */ + dqc_unit[drv].FNC = FNC_SEEK2; /* advance state */ + break; -case FNC_STA: /* read status */ - if (CMD (devd)) { /* dch active? */ - if ((dqc_unit[drv].flags & UNIT_UNLOAD) == 0) /* drive up? */ - dqd_ibuf = dqc_sta[drv] & ~STA_DID; - else dqd_ibuf = STA_NRDY; - if (dqd_ibuf & STA_ANYERR) /* errors? set flg */ - dqd_ibuf = dqd_ibuf | STA_ERR; - if (drv) dqd_ibuf = dqd_ibuf | STA_DID; - setFSR (devd); /* set dch flg */ - clrCMD (devd); /* clr dch cmd */ - clrCMD (devc); /* clr cch cmd */ - dqc_sta[drv] = dqc_sta[drv] & ~STA_ANYERR; /* clr sta flags */ - } - else sim_activate (uptr, dqc_xtime); /* wait more */ - break; + case FNC_STA: /* read status */ + if (CMD (devd)) { /* dch active? */ + if ((dqc_unit[drv].flags & UNIT_UNLOAD) == 0) /* drive up? */ + dqd_ibuf = dqc_sta[drv] & ~STA_DID; + else dqd_ibuf = STA_NRDY; + if (dqd_ibuf & STA_ANYERR) /* errors? set flg */ + dqd_ibuf = dqd_ibuf | STA_ERR; + if (drv) dqd_ibuf = dqd_ibuf | STA_DID; + setFSR (devd); /* set dch flg */ + clrCMD (devd); /* clr dch cmd */ + clrCMD (devc); /* clr cch cmd */ + dqc_sta[drv] = dqc_sta[drv] & ~STA_ANYERR; /* clr sta flags */ + } + 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 */ - dq_goc (FNC_CHK1, drv, dqc_ctime); } /* sched drv */ - 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 */ + dq_goc (FNC_CHK1, drv, dqc_ctime); /* sched drv */ + } + else sim_activate (uptr, dqc_xtime); /* wait more */ + break; + + default: + return SCPE_IERR; + } -default: - return SCPE_IERR; } return SCPE_OK; } - + /* Drive unit service This routine handles the data transfers. Seek substates - seek2 - done + seek2 - done Recalibrate substate - rcl1 - done + rcl1 - done Check data substates - chk1 - finish operation + chk1 - finish operation Read Read address Address skip (read without header check) @@ -525,157 +563,177 @@ return SCPE_OK; */ #define GETDA(x,y,z) \ - (((((x) * DQ_NUMSF) + (y)) * DQ_NUMSC) + (z)) * DQ_NUMWD + (((((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_UNLOAD) { /* drive down? */ - setFSR (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 */ +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_UNLOAD) { /* drive down? */ + setFSR (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 (dqc_ucyl[drv] >= DQ_NUMCY) { /* out of range? */ - dqc_sta[drv] = dqc_sta[drv] | STA_BSY | STA_ERR; /* seek check */ - dqc_ucyl[drv] = 0; } /* seek to 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 { - setFSR (devc); /* set cch flg */ - clrCMD (devc); } /* clr cch cmd */ - return SCPE_OK; + case FNC_SEEK2: /* seek done */ + if (dqc_ucyl[drv] >= DQ_NUMCY) { /* out of range? */ + dqc_sta[drv] = dqc_sta[drv] | STA_BSY | STA_ERR; /* seek check */ + dqc_ucyl[drv] = 0; /* seek to 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 { + setFSR (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 = dqc_ucyl[drv]; /* 1st word? */ - else if (dq_ptr == 1) { /* second word? */ - dqd_ibuf = (dqc_uhed[drv] << DA_V_HD) | /* use drive head */ - (dqc_rars << DA_V_SC); /* and RAR sector */ - dqc_rars = (dqc_rars + 1) % DQ_NUMSC; } /* incr sector */ - else break; - dq_ptr = dq_ptr + 1; - setFSR (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 ((dqc_rarc != dqc_ucyl[drv]) || /* RAR cyl miscompare? */ - (dqc_rarh != dqc_uhed[drv]) || /* RAR head miscompare? */ - (dqc_rars >= DQ_NUMSC)) { /* bad sector? */ - dqc_sta[drv] = dqc_sta[drv] | STA_AER; /* no record found err */ - break; } - if (dqc_rarh >= DQ_NUMSF) { /* bad head? */ - dqc_sta[drv] = dqc_sta[drv] | STA_EOC; /* end of cyl err */ - break; } - da = GETDA (dqc_rarc, dqc_rarh, dqc_rars); /* calc disk addr */ - dqc_rars = (dqc_rars + 1) % DQ_NUMSC; /* incr sector */ - if (dqc_rars == 0) /* wrap? incr head */ - dqc_uhed[drv] = dqc_rarh = dqc_rarh + 1; - 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? */ - setFSR (devd); } /* set flag */ - clrCMD (devd); /* clr dch cmd */ - sim_activate (uptr, dqc_xtime); /* sched next word */ - return SCPE_OK; + case FNC_RA: /* read addr */ + if (!CMD (devd)) break; /* dch clr? done */ + if (dq_ptr == 0) dqd_ibuf = dqc_ucyl[drv]; /* 1st word? */ + else if (dq_ptr == 1) { /* second word? */ + dqd_ibuf = (dqc_uhed[drv] << DA_V_HD) | /* use drive head */ + (dqc_rars << DA_V_SC); /* and RAR sector */ + dqc_rars = (dqc_rars + 1) % DQ_NUMSC; /* incr sector */ + } + else break; + dq_ptr = dq_ptr + 1; + setFSR (devd); /* set dch flg */ + 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; - break; } /* done */ - if ((dqc_rarc != dqc_ucyl[drv]) || /* RAR cyl miscompare? */ - (dqc_rarh != dqc_uhed[drv]) || /* RAR head miscompare? */ - (dqc_rars >= DQ_NUMSC)) { /* bad sector? */ - dqc_sta[drv] = dqc_sta[drv] | STA_AER; /* no record found err */ - break; } - if (dqc_rarh >= DQ_NUMSF) { /* bad head? */ - dqc_sta[drv] = dqc_sta[drv] | STA_EOC; /* end of cyl err */ - break; } } - 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, dqc_rarh, dqc_rars); /* calc disk addr */ - dqc_rars = (dqc_rars + 1) % DQ_NUMSC; /* incr sector */ - if (dqc_rars == 0) /* wrap? incr head */ - dqc_uhed[drv] = dqc_rarh = dqc_rarh + 1; - 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? */ - setFSR (devd); } /* set flag */ - 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 ((dqc_rarc != dqc_ucyl[drv]) || /* RAR cyl miscompare? */ + (dqc_rarh != dqc_uhed[drv]) || /* RAR head miscompare? */ + (dqc_rars >= DQ_NUMSC)) { /* bad sector? */ + dqc_sta[drv] = dqc_sta[drv] | STA_AER; /* no record found err */ + break; + } + if (dqc_rarh >= DQ_NUMSF) { /* bad head? */ + dqc_sta[drv] = dqc_sta[drv] | STA_EOC; /* end of cyl err */ + break; + } + da = GETDA (dqc_rarc, dqc_rarh, dqc_rars); /* calc disk addr */ + dqc_rars = (dqc_rars + 1) % DQ_NUMSC; /* incr sector */ + if (dqc_rars == 0) /* wrap? incr head */ + dqc_uhed[drv] = dqc_rarh = dqc_rarh + 1; + 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? */ + setFSR (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 */ + 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; + break; /* done */ + } + if ((dqc_rarc != dqc_ucyl[drv]) || /* RAR cyl miscompare? */ + (dqc_rarh != dqc_uhed[drv]) || /* RAR head miscompare? */ + (dqc_rars >= DQ_NUMSC)) { /* bad sector? */ + dqc_sta[drv] = dqc_sta[drv] | STA_AER; /* no record found err */ + break; + } + if (dqc_rarh >= DQ_NUMSF) { /* bad head? */ + dqc_sta[drv] = dqc_sta[drv] | STA_EOC; /* end of cyl err */ + break; + } + } + 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, dqc_rarh, dqc_rars); /* calc disk addr */ + dqc_rars = (dqc_rars + 1) % DQ_NUMSC; /* incr sector */ + if (dqc_rars == 0) /* wrap? incr head */ + dqc_uhed[drv] = dqc_rarh = dqc_rarh + 1; + 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? */ + setFSR (devd); /* set flag */ + } + clrCMD (devd); /* clr dch cmd */ + sim_activate (uptr, dqc_xtime); /* sched next word */ + return SCPE_OK; -setFSR (devc); /* set cch flg */ -clrCMD (devc); /* clr cch cmd */ -dqc_busy = 0; /* ctlr is free */ + default: + return SCPE_IERR; + } /* end case fnc */ + +setFSR (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; } +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 drv; -hp_enbdis_pair (dptr, /* make pair cons */ - (dptr == &dqd_dev)? &dqc_dev: &dqd_dev); -dqd_ibuf = dqd_obuf = 0; /* clear buffers */ +hp_enbdis_pair (dptr, /* make pair cons */ + (dptr == &dqd_dev)? &dqc_dev: &dqd_dev); +dqd_ibuf = dqd_obuf = 0; /* clear buffers */ dqc_busy = dqc_obuf = 0; dqd_xfer = dqd_wval = 0; dq_ptr = 0; -dqc_rarc = dqc_rarh = dqc_rars = 0; /* clear RAR */ -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 */ -dqc_dib.srq = dqd_dib.srq = 1; /* srq follows flg */ -sim_cancel (&dqd_unit); /* cancel dch */ -for (drv = 0; drv < DQ_NUMDRV; drv++) { /* loop thru drives */ - sim_cancel (&dqc_unit[drv]); /* cancel activity */ - dqc_unit[drv].FNC = 0; /* clear function */ - dqc_ucyl[drv] = dqc_uhed[drv] = 0; /* clear drive pos */ - dqc_sta[drv] = 0; } /* clear status */ +dqc_rarc = dqc_rarh = dqc_rars = 0; /* clear RAR */ +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 */ +dqc_dib.srq = dqd_dib.srq = 1; /* srq follows flg */ +sim_cancel (&dqd_unit); /* cancel dch */ +for (drv = 0; drv < DQ_NUMDRV; drv++) { /* loop thru drives */ + sim_cancel (&dqc_unit[drv]); /* cancel activity */ + dqc_unit[drv].FNC = 0; /* clear function */ + dqc_ucyl[drv] = dqc_uhed[drv] = 0; /* clear drive pos */ + dqc_sta[drv] = 0; /* clear status */ + } return SCPE_OK; } @@ -685,7 +743,7 @@ t_stat dqc_attach (UNIT *uptr, char *cptr) { t_stat r; -r = attach_unit (uptr, cptr); /* attach unit */ +r = attach_unit (uptr, cptr); /* attach unit */ if (r == SCPE_OK) dqc_load_unload (uptr, 0, NULL, NULL);/* if OK, load heads */ return r; } @@ -694,96 +752,97 @@ return r; t_stat dqc_detach (UNIT* uptr) { -dqc_load_unload (uptr, UNIT_UNLOAD, NULL, NULL); /* unload heads */ -return detach_unit (uptr); /* detach unit */ +dqc_load_unload (uptr, UNIT_UNLOAD, NULL, NULL); /* unload heads */ +return detach_unit (uptr); /* detach unit */ } /* Load and unload heads */ t_stat dqc_load_unload (UNIT *uptr, int32 value, char *cptr, void *desc) { -if ((uptr->flags & UNIT_ATT) == 0) return SCPE_UNATT; /* must be attached to load */ -if (value == UNIT_UNLOAD) /* unload heads? */ - uptr->flags = uptr->flags | UNIT_UNLOAD; /* indicate unload */ -else uptr->flags = uptr->flags & ~UNIT_UNLOAD; /* indicate load */ +if ((uptr->flags & UNIT_ATT) == 0) return SCPE_UNATT; /* must be attached to load */ +if (value == UNIT_UNLOAD) /* unload heads? */ + uptr->flags = uptr->flags | UNIT_UNLOAD; /* indicate unload */ +else uptr->flags = uptr->flags & ~UNIT_UNLOAD; /* indicate load */ return SCPE_OK; } /* 7900/7901/2883/2884 bootstrap routine (HP 12992A ROM) */ const uint16 dq_rom[IBL_LNT] = { - 0102501, /*ST LIA 1 ; get switches */ - 0106501, /* LIB 1 */ - 0013765, /* AND D7 ; isolate hd */ - 0005750, /* BLF,CLE,SLB */ - 0027741, /* JMP RD */ - 0005335, /* RBR,SLB,ERB ; <13>->E, set = 2883 */ - 0027717, /* JMP IS */ - 0102611, /*LP OTA CC ; do 7900 status to */ - 0103711, /* STC CC,C ; clear first seek */ - 0102310, /* SFS DC */ - 0027711, /* JMP *-1 */ - 0002004, /* INA ; get next drive */ - 0053765, /* CPA D7 ; all cleared? */ - 0002001, /* RSS */ - 0027707, /* JMP LP */ - 0067761, /*IS LDB SEEKC ; get seek comnd */ - 0106610, /* OTB DC ; issue cyl addr (0) */ - 0103710, /* STC DC,C ; to dch */ - 0106611, /* OTB CC ; seek cmd */ - 0103711, /* STC CC,C ; to cch */ - 0102310, /* SFS DC ; addr wd ok? */ - 0027724, /* JMP *-1 ; no, wait */ - 0006400, /* CLB */ - 0102501, /* LIA 1 ; get switches */ - 0002051, /* SEZ,SLA,RSS ; subchan = 1 or ISS */ - 0047770, /* ADB BIT9 ; head 2 */ - 0106610, /* OTB DC ; head/sector */ - 0103710, /* STC DC,C ; to dch */ - 0102311, /* SFS CC ; seek done? */ - 0027734, /* JMP *-1 ; no, wait */ - 0063731, /* LDA ISSRD ; get read read */ - 0002341, /* SEZ,CCE,RSS ; iss disc? */ - 0001100, /* ARS ; no, make 7900 read */ - 0067776, /*RD LDB DMACW ; DMA control */ - 0106606, /* OTB 6 */ - 0067762, /* LDB ADDR1 ; memory addr */ - 0077741, /* STB RD ; make non re-executable */ - 0106602, /* OTB 2 */ - 0102702, /* STC 2 ; flip DMA ctrl */ - 0067764, /* LDB COUNT ; word count */ - 0106602, /* OTB 2 */ - 0002041, /* SEZ,RSS */ - 0027766, /* JMP NW */ - 0102611, /* OTA CC ; to cch */ - 0103710, /* STC DC,C ; start dch */ - 0103706, /* STC 6,C ; start DMA */ - 0103711, /* STC CC,C ; start cch */ - 0037773, /* ISZ SK */ - 0027773, /* JMP SK */ - 0030000, /*SEEKC 030000 */ - 0102011, /*ADDR1 102011 */ - 0102055, /*ADDR2 102055 */ - 0164000, /*COUNT -6144. */ - 0000007, /*D7 7 */ - 0106710, /*NW CLC DC ; set 'next wd is cmd' flag */ - 0001720, /* ALF,ALF ; move to head number loc */ - 0001000, /*BIT9 ALS */ - 0103610, /* OTA DC,C ; output cold load cmd */ - 0103706, /* STC 6,C ; start DMA */ - 0102310, /* SFS DC ; done? */ - 0027773, /* JMP *-1 ; no, wait */ - 0117763, /*XT JSB ADDR2,I ; start program */ - 0120010, /*DMACW 120000+DC */ - 0000000 }; /* -ST */ + 0102501, /*ST LIA 1 ; get switches */ + 0106501, /* LIB 1 */ + 0013765, /* AND D7 ; isolate hd */ + 0005750, /* BLF,CLE,SLB */ + 0027741, /* JMP RD */ + 0005335, /* RBR,SLB,ERB ; <13>->E, set = 2883 */ + 0027717, /* JMP IS */ + 0102611, /*LP OTA CC ; do 7900 status to */ + 0103711, /* STC CC,C ; clear first seek */ + 0102310, /* SFS DC */ + 0027711, /* JMP *-1 */ + 0002004, /* INA ; get next drive */ + 0053765, /* CPA D7 ; all cleared? */ + 0002001, /* RSS */ + 0027707, /* JMP LP */ + 0067761, /*IS LDB SEEKC ; get seek comnd */ + 0106610, /* OTB DC ; issue cyl addr (0) */ + 0103710, /* STC DC,C ; to dch */ + 0106611, /* OTB CC ; seek cmd */ + 0103711, /* STC CC,C ; to cch */ + 0102310, /* SFS DC ; addr wd ok? */ + 0027724, /* JMP *-1 ; no, wait */ + 0006400, /* CLB */ + 0102501, /* LIA 1 ; get switches */ + 0002051, /* SEZ,SLA,RSS ; subchan = 1 or ISS */ + 0047770, /* ADB BIT9 ; head 2 */ + 0106610, /* OTB DC ; head/sector */ + 0103710, /* STC DC,C ; to dch */ + 0102311, /* SFS CC ; seek done? */ + 0027734, /* JMP *-1 ; no, wait */ + 0063731, /* LDA ISSRD ; get read read */ + 0002341, /* SEZ,CCE,RSS ; iss disc? */ + 0001100, /* ARS ; no, make 7900 read */ + 0067776, /*RD LDB DMACW ; DMA control */ + 0106606, /* OTB 6 */ + 0067762, /* LDB ADDR1 ; memory addr */ + 0077741, /* STB RD ; make non re-executable */ + 0106602, /* OTB 2 */ + 0102702, /* STC 2 ; flip DMA ctrl */ + 0067764, /* LDB COUNT ; word count */ + 0106602, /* OTB 2 */ + 0002041, /* SEZ,RSS */ + 0027766, /* JMP NW */ + 0102611, /* OTA CC ; to cch */ + 0103710, /* STC DC,C ; start dch */ + 0103706, /* STC 6,C ; start DMA */ + 0103711, /* STC CC,C ; start cch */ + 0037773, /* ISZ SK */ + 0027773, /* JMP SK */ + 0030000, /*SEEKC 030000 */ + 0102011, /*ADDR1 102011 */ + 0102055, /*ADDR2 102055 */ + 0164000, /*COUNT -6144. */ + 0000007, /*D7 7 */ + 0106710, /*NW CLC DC ; set 'next wd is cmd' flag */ + 0001720, /* ALF,ALF ; move to head number loc */ + 0001000, /*BIT9 ALS */ + 0103610, /* OTA DC,C ; output cold load cmd */ + 0103706, /* STC 6,C ; start DMA */ + 0102310, /* SFS DC ; done? */ + 0027773, /* JMP *-1 ; no, wait */ + 0117763, /*XT JSB ADDR2,I ; start program */ + 0120010, /*DMACW 120000+DC */ + 0000000 /* -ST */ + }; t_stat dqc_boot (int32 unitno, DEVICE *dptr) { int32 dev; -if (unitno != 0) return SCPE_NOFNC; /* only unit 0 */ -dev = dqd_dib.devno; /* get data chan dev */ -if (ibl_copy (dq_rom, dev)) return SCPE_IERR; /* copy boot to memory */ -SR = (SR & IBL_OPT) | IBL_DQ | (dev << IBL_V_DEV); /* set SR */ +if (unitno != 0) return SCPE_NOFNC; /* only unit 0 */ +dev = dqd_dib.devno; /* get data chan dev */ +if (ibl_copy (dq_rom, dev)) return SCPE_IERR; /* copy boot to memory */ +SR = (SR & IBL_OPT) | IBL_DQ | (dev << IBL_V_DEV); /* set SR */ return SCPE_OK; } diff --git a/HP2100/hp2100_dr.c b/HP2100/hp2100_dr.c index c1299a76..8bf8baf5 100644 --- a/HP2100/hp2100_dr.c +++ b/HP2100/hp2100_dr.c @@ -1,6 +1,6 @@ /* hp2100_dr.c: HP 2100 12606B/12610B fixed head disk/drum simulator - Copyright (c) 1993-2004, Robert M. Supnik + Copyright (c) 1993-2005, 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"), @@ -19,32 +19,32 @@ 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 + 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. - dr 12606B 2770/2771 fixed head disk - 12610B 2773/2774/2775 drum + dr 12606B 2770/2771 fixed head disk + 12610B 2773/2774/2775 drum - 07-Oct-04 JDB Fixed enable/disable from either device - Fixed sector return in status word - Provided protected tracks and "Writing Enabled" status bit - Fixed DMA last word write, incomplete sector fill value - Added "parity error" status return on writes for 12606 - Added track origin test for 12606 - Added SCP test for 12606 - Fixed 12610 SFC operation - Added "Sector Flag" status bit - Added "Read Inhibit" status bit for 12606 - Fixed current-sector determination - Added PROTECTED, UNPROTECTED, TRACKPROT modifiers - 26-Aug-04 RMS Fixed CLC to stop operation (from Dave Bryan) - 26-Apr-04 RMS Fixed SFS x,C and SFC x,C - Revised boot rom to use IBL algorithm - Implemented DMA SRQ (follows FLG) - 27-Jul-03 RMS Fixed drum sizes - Fixed variable capacity interaction with SAVE/RESTORE - 10-Nov-02 RMS Added BOOT command + 07-Oct-04 JDB Fixed enable/disable from either device + Fixed sector return in status word + Provided protected tracks and "Writing Enabled" status bit + Fixed DMA last word write, incomplete sector fill value + Added "parity error" status return on writes for 12606 + Added track origin test for 12606 + Added SCP test for 12606 + Fixed 12610 SFC operation + Added "Sector Flag" status bit + Added "Read Inhibit" status bit for 12606 + Fixed current-sector determination + Added PROTECTED, UNPROTECTED, TRACKPROT modifiers + 26-Aug-04 RMS Fixed CLC to stop operation (from Dave Bryan) + 26-Apr-04 RMS Fixed SFS x,C and SFC x,C + Revised boot rom to use IBL algorithm + Implemented DMA SRQ (follows FLG) + 27-Jul-03 RMS Fixed drum sizes + Fixed variable capacity interaction with SAVE/RESTORE + 10-Nov-02 RMS Added BOOT command These head-per-track devices are buffered in memory, to minimize overhead. @@ -102,87 +102,87 @@ /* 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 DR_FTIME 4 /* fhd per-word time */ -#define DR_DTIME 6 /* drum per-word time */ -#define DR_OVRHEAD 5 /* overhead words at track start */ -#define UNIT_V_PROT (UNIT_V_UF + 0) /* track protect */ -#define UNIT_V_SZ (UNIT_V_UF + 1) /* disk vs drum */ -#define UNIT_M_SZ 017 /* size */ -#define UNIT_PROT (1 << UNIT_V_PROT) -#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) +#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 DR_FTIME 4 /* fhd per-word time */ +#define DR_DTIME 6 /* drum per-word time */ +#define DR_OVRHEAD 5 /* overhead words at track start */ +#define UNIT_V_PROT (UNIT_V_UF + 0) /* track protect */ +#define UNIT_V_SZ (UNIT_V_UF + 1) /* disk vs drum */ +#define UNIT_M_SZ 017 /* size */ +#define UNIT_PROT (1 << UNIT_V_PROT) +#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)) +#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, ^ = dynamic */ -#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 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 CALC_SCP(x) (((int32) fmod ((x) / (double) dr_time, \ + (double) (DR_NUMWD))) >= (DR_NUMWD - 3)) -#define CALC_SCP(x) (((int32) fmod ((x) / (double) dr_time, \ - (double) (DR_NUMWD))) >= (DR_NUMWD - 3)) - extern UNIT cpu_unit; extern uint16 *M; extern uint32 PC; extern uint32 dev_cmd[2], dev_ctl[2], dev_flg[2], dev_fbf[2], dev_srq[2]; -int32 drc_cw = 0; /* fnc, addr */ -int32 drc_sta = 0; /* status */ -int32 drc_run = 0; /* run flip-flop */ -int32 drd_ibuf = 0; /* input buffer */ -int32 drd_obuf = 0; /* output buffer */ -int32 drd_ptr = 0; /* sector pointer */ -int32 drc_pcount = 1; /* number of prot tracks */ -int32 dr_stopioe = 1; /* stop on error */ -int32 dr_time = DR_DTIME; /* time per word */ +int32 drc_cw = 0; /* fnc, addr */ +int32 drc_sta = 0; /* status */ +int32 drc_run = 0; /* run flip-flop */ +int32 drd_ibuf = 0; /* input buffer */ +int32 drd_obuf = 0; /* output buffer */ +int32 drd_ptr = 0; /* sector pointer */ +int32 drc_pcount = 1; /* number of prot tracks */ +int32 dr_stopioe = 1; /* stop on error */ +int32 dr_time = DR_DTIME; /* time per word */ static int32 sz_tab[16] = { 184320, 1048576, 368640, 1572864, 737280, 393216, 0, 524288, @@ -202,256 +202,291 @@ 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 + drd_dev device descriptor + drd_unit unit descriptor + drd_reg register list */ DIB dr_dib[] = { - { DRD, 0, 0, 0, 0, 0, &drdio }, - { DRC, 0, 0, 0, 0, 0, &drcio } }; + { DRD, 0, 0, 0, 0, 0, &drdio }, + { DRC, 0, 0, 0, 0, 0, &drcio } + }; #define drd_dib dr_dib[0] #define drc_dib dr_dib[1] UNIT drd_unit[] = { - { UDATA (NULL, 0, 0) }, - { UDATA (NULL, UNIT_DIS, 0) } }; + { UDATA (NULL, 0, 0) }, + { UDATA (NULL, UNIT_DIS, 0) } + }; -#define TMR_ORG 0 /* origin timer */ -#define TMR_INH 1 /* inhibit timer */ +#define TMR_ORG 0 /* origin timer */ +#define TMR_INH 1 /* inhibit timer */ 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) }, - { FLDATA (SRQ, drd_dib.srq, 0) }, - { ORDATA (BPTR, drd_ptr, 6) }, - { ORDATA (DEVNO, drd_dib.devno, 6), REG_HRO }, - { NULL } }; + { 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) }, + { FLDATA (SRQ, drd_dib.srq, 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 } }; + { MTAB_XTD | MTAB_VDV, 1, "DEVNO", "DEVNO", + &hp_setdev, &hp_showdev, &drd_dev }, + { 0 } + }; DEVICE drd_dev = { - "DRD", drd_unit, drd_reg, drd_mod, - 2, 0, 0, 0, 0, 0, - NULL, NULL, &drc_reset, - NULL, NULL, NULL, - &drd_dib, DEV_DISABLE }; + "DRD", drd_unit, drd_reg, drd_mod, + 2, 0, 0, 0, 0, 0, + NULL, NULL, &drc_reset, + 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 + 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) }; +UNIT drc_unit = { + UDATA (&drc_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_BUFABLE+ + UNIT_MUSTBUF+UNIT_DR+UNIT_BINK, DR_SIZE) + }; REG drc_reg[] = { - { DRDATA (PCNT, drc_pcount, 10), REG_HIDDEN | PV_LEFT }, - { ORDATA (CW, drc_cw, 16) }, - { ORDATA (STA, drc_sta, 16) }, - { FLDATA (RUN, drc_run, 0) }, - { FLDATA (CMD, drc_dib.cmd, 0) }, - { FLDATA (CTL, drc_dib.ctl, 0) }, - { FLDATA (FLG, drc_dib.flg, 0) }, - { FLDATA (FBF, drc_dib.fbf, 0) }, - { FLDATA (SRQ, drc_dib.srq, 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 } }; + { DRDATA (PCNT, drc_pcount, 10), REG_HIDDEN | PV_LEFT }, + { ORDATA (CW, drc_cw, 16) }, + { ORDATA (STA, drc_sta, 16) }, + { FLDATA (RUN, drc_run, 0) }, + { FLDATA (CMD, drc_dib.cmd, 0) }, + { FLDATA (CTL, drc_dib.ctl, 0) }, + { FLDATA (FLG, drc_dib.flg, 0) }, + { FLDATA (FBF, drc_dib.fbf, 0) }, + { FLDATA (SRQ, drc_dib.srq, 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 }, - { UNIT_PROT, UNIT_PROT, "protected", "PROTECTED", NULL }, - { UNIT_PROT, 0, "unprotected", "UNPROTECTED", NULL }, - { MTAB_XTD | MTAB_VDV | MTAB_VAL, 0, "tracks protected", "TRACKPROT", - &dr_set_prot, NULL, &drc_reg[0] }, - { MTAB_XTD | MTAB_VDV, 1, "DEVNO", "DEVNO", - &hp_setdev, &hp_showdev, &drd_dev }, - { 0 } }; + { 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 }, + { UNIT_PROT, UNIT_PROT, "protected", "PROTECTED", NULL }, + { UNIT_PROT, 0, "unprotected", "UNPROTECTED", NULL }, + { MTAB_XTD | MTAB_VDV | MTAB_VAL, 0, "tracks protected", "TRACKPROT", + &dr_set_prot, NULL, &drc_reg[0] }, + { 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 */ + "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 + }; + +/* IO instructions */ 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" */ - clrFSR (devd); /* clr flg */ - if (!drc_run) sim_cancel (&drc_unit); /* cancel curr op */ - 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) { setFSR (devd); } /* prime DMA */ - drc_sta = 0; /* clr status */ - drd_ptr = 0; /* clear sec ptr */ - sim_cancel (&drc_unit); /* cancel curr op */ - t = CW_GETSEC (drc_cw) - dr_seccntr (sim_gtime()); - if (t <= 0) t = t + DR_NUMSC; - sim_activate (&drc_unit, t * DR_NUMWD * dr_time); } - break; -default: - break; } -if (IR & I_HC) { clrFSR (devd); } /* H/C option */ +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" */ + clrFSR (devd); /* clr flg */ + if (!drc_run) sim_cancel (&drc_unit); /* cancel curr op */ + 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) { setFSR (devd); } /* prime DMA */ + drc_sta = 0; /* clr status */ + drd_ptr = 0; /* clear sec ptr */ + sim_cancel (&drc_unit); /* cancel curr op */ + t = CW_GETSEC (drc_cw) - dr_seccntr (sim_gtime()); + if (t <= 0) t = t + DR_NUMSC; + sim_activate (&drc_unit, t * DR_NUMWD * dr_time); + } + break; + + default: + break; + } + +if (IR & I_HC) { clrFSR (devd); } /* H/C option */ return dat; } - + int32 drcio (int32 inst, int32 IR, int32 dat) { int32 sec; -switch (inst) { /* case on opcode */ -case ioFLG: /* flag clear/set */ - if ((IR & I_HC) && !(drc_unit.flags & UNIT_DR)) { /* CLF disk */ - sec = dr_seccntr (sim_gtime ()); /* current sector */ - sim_cancel (&drd_unit[TMR_ORG]); /* sched origin tmr */ - sim_activate (&drd_unit[TMR_ORG], - (DR_FNUMSC - sec) * DR_NUMWD * dr_time); } - break; -case ioSFC: /* skip flag clear */ - if (drc_unit.flags & UNIT_DR) break; /* 12610 never skips */ - if (!(CALC_SCP (sim_gtime()))) /* nearing end of sector? */ - PC = (PC + 1) & VAMASK; /* skip if SCP clear */ - break; -case ioSFS: /* skip flag set */ - if (drc_unit.flags & UNIT_DR) break; /* 12610 never skips */ - if (!sim_is_active (&drd_unit[TMR_ORG])) /* passed origin? */ - PC = (PC + 1) & VAMASK; /* skip if origin seen */ - break; -case ioOTX: /* output */ - if (!(drc_unit.flags & UNIT_DR)) { /* disk? */ - sim_cancel (&drd_unit[TMR_INH]); /* schedule inhibit timer */ - sim_activate (&drd_unit[TMR_INH], DR_FTIME * DR_NUMWD); } - drc_cw = dat; /* get control word */ - break; -case ioLIX: /* load */ - dat = 0; -case ioMIX: /* merge */ - dat = dat | drc_sta; /* static bits */ - if (!(drc_unit.flags & UNIT_PROT) || /* not protected? */ - (CW_GETTRK(drc_cw) >= drc_pcount)) /* or not in range? */ - dat = dat | DRS_WEN; /* set wrt enb status */ - if (drc_unit.flags & UNIT_ATT) { /* attached? */ - dat = dat | (dr_seccntr (sim_gtime()) << DRS_V_NS) | DRS_RDY; - if (sim_is_active (&drc_unit)) /* op in progress? */ - dat = dat | DRS_BSY; - if (CALC_SCP (sim_gtime())) /* SCP ff set? */ - dat = dat | DRS_SEC; /* set sector flag */ - if (sim_is_active (&drd_unit[TMR_INH]) && /* inhibit timer on? */ - !(drc_cw & CW_WR)) - dat = dat | DRS_RIF; } /* set read inh flag */ - break; -default: - break; } +switch (inst) { /* case on opcode */ + + case ioFLG: /* flag clear/set */ + if ((IR & I_HC) && !(drc_unit.flags & UNIT_DR)) { /* CLF disk */ + sec = dr_seccntr (sim_gtime ()); /* current sector */ + sim_cancel (&drd_unit[TMR_ORG]); /* sched origin tmr */ + sim_activate (&drd_unit[TMR_ORG], + (DR_FNUMSC - sec) * DR_NUMWD * dr_time); + } + break; + + case ioSFC: /* skip flag clear */ + if (drc_unit.flags & UNIT_DR) break; /* 12610 never skips */ + if (!(CALC_SCP (sim_gtime()))) /* nearing end of sector? */ + PC = (PC + 1) & VAMASK; /* skip if SCP clear */ + break; + + case ioSFS: /* skip flag set */ + if (drc_unit.flags & UNIT_DR) break; /* 12610 never skips */ + if (!sim_is_active (&drd_unit[TMR_ORG])) /* passed origin? */ + PC = (PC + 1) & VAMASK; /* skip if origin seen */ + break; + + case ioOTX: /* output */ + if (!(drc_unit.flags & UNIT_DR)) { /* disk? */ + sim_cancel (&drd_unit[TMR_INH]); /* schedule inhibit timer */ + sim_activate (&drd_unit[TMR_INH], DR_FTIME * DR_NUMWD); + } + drc_cw = dat; /* get control word */ + break; + + case ioLIX: /* load */ + dat = 0; + case ioMIX: /* merge */ + dat = dat | drc_sta; /* static bits */ + if (!(drc_unit.flags & UNIT_PROT) || /* not protected? */ + (CW_GETTRK(drc_cw) >= drc_pcount)) /* or not in range? */ + dat = dat | DRS_WEN; /* set wrt enb status */ + if (drc_unit.flags & UNIT_ATT) { /* attached? */ + dat = dat | (dr_seccntr (sim_gtime()) << DRS_V_NS) | DRS_RDY; + if (sim_is_active (&drc_unit)) /* op in progress? */ + dat = dat | DRS_BSY; + if (CALC_SCP (sim_gtime())) /* SCP ff set? */ + dat = dat | DRS_SEC; /* set sector flag */ + if (sim_is_active (&drd_unit[TMR_INH]) && /* inhibit timer on? */ + !(drc_cw & CW_WR)) + dat = dat | DRS_RIF; /* set read inh flag */ + } + break; + + default: + break; + } + return dat; } - + /* Unit service */ t_stat drc_svc (UNIT *uptr) { int32 devd, trk, sec; uint32 da; -uint16 *bptr = uptr->filebuf; +uint16 *bptr = (uint16 *) uptr->filebuf; if ((uptr->flags & UNIT_ATT) == 0) { - drc_sta = DRS_ABO; - return IORETURN (dr_stopioe, SCPE_UNATT); } + drc_sta = DRS_ABO; + return IORETURN (dr_stopioe, SCPE_UNATT); + } -devd = drd_dib.devno; /* get dch devno */ +devd = drd_dib.devno; /* get dch devno */ trk = CW_GETTRK (drc_cw); sec = CW_GETSEC (drc_cw); da = ((trk * DR_NUMSC) + sec) * DR_NUMWD; drc_sta = drc_sta | DRS_SAC; -drc_run = 1; /* set run ff */ +drc_run = 1; /* set run ff */ -if (drc_cw & CW_WR) { /* write? */ - if ((da < uptr->capac) && (sec < DR_NUMSC)) { - bptr[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? */ - setFSR (devd); /* set dch flg */ - sim_activate (uptr, dr_time); } /* sched next word */ - else { /* done */ - if (drd_ptr) /* need to fill? */ - for ( ; drd_ptr < DR_NUMWD; drd_ptr++) - bptr[da + drd_ptr] = drd_obuf; /* fill with last word */ - if (!(drc_unit.flags & UNIT_DR)) /* disk? */ - drc_sta = drc_sta | DRS_PER; /* parity bit sets on write */ - drc_run = 0; } /* clear run ff */ - } /* end write */ -else { /* read */ - if (CMD (devd)) { /* dch active? */ - if ((da >= uptr->capac) || (sec >= DR_NUMSC)) drd_ibuf = 0; - else drd_ibuf = bptr[da + drd_ptr]; - drd_ptr = dr_incda (trk, sec, drd_ptr); - setFSR (devd); /* set dch flg */ - sim_activate (uptr, dr_time); } /* sched next word */ - else drc_run = 0; /* clear run ff */ - } +if (drc_cw & CW_WR) { /* write? */ + if ((da < uptr->capac) && (sec < DR_NUMSC)) { + bptr[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? */ + setFSR (devd); /* set dch flg */ + sim_activate (uptr, dr_time); /* sched next word */ + } + else { /* done */ + if (drd_ptr) /* need to fill? */ + for ( ; drd_ptr < DR_NUMWD; drd_ptr++) + bptr[da + drd_ptr] = drd_obuf; /* fill with last word */ + if (!(drc_unit.flags & UNIT_DR)) /* disk? */ + drc_sta = drc_sta | DRS_PER; /* parity bit sets on write */ + drc_run = 0; /* clear run ff */ + } + } /* end write */ +else { /* read */ + if (CMD (devd)) { /* dch active? */ + if ((da >= uptr->capac) || (sec >= DR_NUMSC)) drd_ibuf = 0; + else drd_ibuf = bptr[da + drd_ptr]; + drd_ptr = dr_incda (trk, sec, drd_ptr); + setFSR (devd); /* set dch flg */ + sim_activate (uptr, dr_time); /* sched next word */ + } + else drc_run = 0; /* clear run ff */ + } 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); - } +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; } @@ -475,24 +510,24 @@ int32 dr_seccntr (double simtime) int32 curword; curword = (int32) fmod (simtime / (double) dr_time, - (double) (DR_NUMWD * DR_NUMSC + DR_OVRHEAD)); + (double) (DR_NUMWD * DR_NUMSC + DR_OVRHEAD)); if (curword <= DR_OVRHEAD) return 0; else return ((curword - DR_OVRHEAD) / DR_NUMWD + - ((drc_unit.flags & UNIT_DR)? 0: 1)); + ((drc_unit.flags & UNIT_DR)? 0: 1)); } /* Reset routine */ t_stat drc_reset (DEVICE *dptr) { -hp_enbdis_pair (dptr, /* make pair cons */ - (dptr == &drd_dev)? &drc_dev: &drd_dev); +hp_enbdis_pair (dptr, /* make pair cons */ + (dptr == &drd_dev)? &drc_dev: &drd_dev); 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 */ -drc_dib.srq = drd_dib.srq = 0; /* srq follows flg */ +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 */ +drc_dib.srq = drd_dib.srq = 0; /* srq follows flg */ sim_cancel (&drc_unit); sim_cancel (&drd_unit[TMR_ORG]); sim_cancel (&drd_unit[TMR_INH]); @@ -521,24 +556,25 @@ if (cptr == NULL) return SCPE_ARG; count = (int32) get_uint (cptr, 10, 768, &status); if (status != SCPE_OK) return status; else switch (count) { - case 1: - case 2: - case 4: - case 8: - case 16: - case 32: - case 64: - case 128: - drc_pcount = count; - break; - case 256: - case 512: - case 768: - if (drc_unit.flags & UNIT_DR) drc_pcount = count; - else return SCPE_ARG; - break; - default: - return SCPE_ARG; } + case 1: + case 2: + case 4: + case 8: + case 16: + case 32: + case 64: + case 128: + drc_pcount = count; + break; + case 256: + case 512: + case 768: + if (drc_unit.flags & UNIT_DR) drc_pcount = count; + else return SCPE_ARG; + break; + default: + return SCPE_ARG; + } return SCPE_OK; } @@ -553,53 +589,56 @@ if (val < 0) return SCPE_IERR; if ((sz = sz_tab[szindex = DR_GETSZ (val)]) == 0) return SCPE_IERR; if (uptr->flags & UNIT_ATT) return SCPE_ALATT; uptr->capac = sz; -if (szindex & UNIT_DR) dr_time = DR_DTIME; /* drum */ +if (szindex & UNIT_DR) dr_time = DR_DTIME; /* drum */ else { - dr_time = DR_FTIME; /* disk */ - if (drc_pcount > 128) drc_pcount = 128; } /* max prot track count */ + dr_time = DR_FTIME; /* disk */ + if (drc_pcount > 128) drc_pcount = 128; /* max prot track count */ + } return SCPE_OK; } /* Fixed head disk/drum bootstrap routine (disc subset of disc/paper tape loader) */ -#define BOOT_BASE 056 -#define BOOT_START 060 +#define BOOT_BASE 056 +#define BOOT_START 060 static const uint16 dr_rom[IBL_LNT - BOOT_BASE] = { - 0020010, /*DMA 20000+DC */ - 0000000, /* 0 */ - 0107700, /* CLC 0,C */ - 0063756, /* LDA DMA ; DMA ctrl */ - 0102606, /* OTA 6 */ - 0002700, /* CLA,CCE */ - 0102611, /* 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 */ - 0102710, /* STC DC ; start disc */ - 0024077, /*JSF JMP 77 ; go wait */ - 0177700 }; /*M64 -100 */ + 0020010, /*DMA 20000+DC */ + 0000000, /* 0 */ + 0107700, /* CLC 0,C */ + 0063756, /* LDA DMA ; DMA ctrl */ + 0102606, /* OTA 6 */ + 0002700, /* CLA,CCE */ + 0102611, /* 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 */ + 0102710, /* 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; uint16 wd; -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 = BOOT_BASE; i < IBL_LNT; i++) { /* copy bootstrap */ - wd = dr_rom[i - BOOT_BASE]; /* get word */ - if (((wd & I_NMRMASK) == I_IO) && /* IO instruction? */ - ((wd & I_DEVMASK) >= 010) && /* dev >= 10? */ - (I_GETIOOP (wd) != ioHLT)) /* not a HALT? */ - M[ad + i] = (wd + (dev - 010)) & DMASK; - else M[ad + i] = wd; } -PC = ad + BOOT_START; +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 = BOOT_BASE; i < IBL_LNT; i++) { /* copy bootstrap */ + wd = dr_rom[i - BOOT_BASE]; /* get word */ + if (((wd & I_NMRMASK) == I_IO) && /* IO instruction? */ + ((wd & I_DEVMASK) >= 010) && /* dev >= 10? */ + (I_GETIOOP (wd) != ioHLT)) /* not a HALT? */ + M[ad + i] = (wd + (dev - 010)) & DMASK; + else M[ad + i] = wd; + } +PC = ad + BOOT_START; return SCPE_OK; } diff --git a/HP2100/hp2100_ds.c b/HP2100/hp2100_ds.c index 0ec14de9..a769b0ba 100644 --- a/HP2100/hp2100_ds.c +++ b/HP2100/hp2100_ds.c @@ -19,14 +19,14 @@ 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 + 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. - ds 13037 disk controller + ds 13037 disk controller - 18-Mar-05 RMS Added attached test to detach routine - 01-Mar-05 JDB Added SET UNLOAD/LOAD + 18-Mar-05 RMS Added attached test to detach routine + 01-Mar-05 JDB Added SET UNLOAD/LOAD States of the controller: the controller uP runs all the time, but most of the time it is waiting for an event. The simulator only 'runs' the controller @@ -62,196 +62,196 @@ #include "hp2100_defs.h" #include -#define DS_NUMDR 8 /* max drives */ -#define DS_DRMASK (DS_NUMDR - 1) -#define DS_NUMWD 128 /* data words/sec */ -#define DS_NUMWDF 138 /* total words/sec */ -#define DS_FSYNC 0 /* sector offsets */ -#define DS_FCYL 1 -#define DS_FHS 2 -#define DS_FDATA 3 -#define DS_FIFO_SIZE 16 /* fifo size */ -#define DS_FIFO_EMPTY (ds_fifo_cnt == 0) -#define ds_ctrl ds_unit[DS_NUMDR] /* ctrl thread */ -#define ds_timer ds_unit[DS_NUMDR + 1] /* timeout thread */ -#define GET_CURSEC(x,d) ((int32) fmod (sim_gtime() / ((double) (x)), \ - ((double) (drv_tab[d].sc)))) +#define DS_NUMDR 8 /* max drives */ +#define DS_DRMASK (DS_NUMDR - 1) +#define DS_NUMWD 128 /* data words/sec */ +#define DS_NUMWDF 138 /* total words/sec */ +#define DS_FSYNC 0 /* sector offsets */ +#define DS_FCYL 1 +#define DS_FHS 2 +#define DS_FDATA 3 +#define DS_FIFO_SIZE 16 /* fifo size */ +#define DS_FIFO_EMPTY (ds_fifo_cnt == 0) +#define ds_ctrl ds_unit[DS_NUMDR] /* ctrl thread */ +#define ds_timer ds_unit[DS_NUMDR + 1] /* timeout thread */ +#define GET_CURSEC(x,d) ((int32) fmod (sim_gtime() / ((double) (x)), \ + ((double) (drv_tab[d].sc)))) /* Flags in the unit flags word */ -#define UNIT_V_WLK (UNIT_V_UF + 0) /* write locked */ -#define UNIT_V_UNLOAD (UNIT_V_UF + 1) /* heads unloaded */ -#define UNIT_V_DTYPE (UNIT_V_UF + 2) /* disk type */ -#define UNIT_M_DTYPE 3 -#define UNIT_V_AUTO (UNIT_V_UF + 4) /* autosize */ -#define UNIT_V_FMT (UNIT_V_UF + 5) /* format enabled */ -#define UNIT_WLK (1 << UNIT_V_WLK) -#define UNIT_FMT (1 << UNIT_V_FMT) -#define UNIT_DTYPE (UNIT_M_DTYPE << UNIT_V_DTYPE) -#define UNIT_AUTO (1 << UNIT_V_AUTO) -#define UNIT_UNLOAD (1 << UNIT_V_UNLOAD) -#define GET_DTYPE(x) (((x) >> UNIT_V_DTYPE) & UNIT_M_DTYPE) -#define UNIT_WPR (UNIT_WLK | UNIT_RO) /* write prot */ +#define UNIT_V_WLK (UNIT_V_UF + 0) /* write locked */ +#define UNIT_V_UNLOAD (UNIT_V_UF + 1) /* heads unloaded */ +#define UNIT_V_DTYPE (UNIT_V_UF + 2) /* disk type */ +#define UNIT_M_DTYPE 3 +#define UNIT_V_AUTO (UNIT_V_UF + 4) /* autosize */ +#define UNIT_V_FMT (UNIT_V_UF + 5) /* format enabled */ +#define UNIT_WLK (1 << UNIT_V_WLK) +#define UNIT_FMT (1 << UNIT_V_FMT) +#define UNIT_DTYPE (UNIT_M_DTYPE << UNIT_V_DTYPE) +#define UNIT_AUTO (1 << UNIT_V_AUTO) +#define UNIT_UNLOAD (1 << UNIT_V_UNLOAD) +#define GET_DTYPE(x) (((x) >> UNIT_V_DTYPE) & UNIT_M_DTYPE) +#define UNIT_WPR (UNIT_WLK | UNIT_RO) /* write prot */ /* Parameters in the unit descriptor */ -#define FNC u3 /* function */ -#define CYL u4 /* current cylinder */ -#define STA u5 /* status */ +#define FNC u3 /* function */ +#define CYL u4 /* current cylinder */ +#define STA u5 /* status */ /* Arguments to subroutines */ -#define CLR_BUSY 0 /* clear visible busy */ -#define SET_BUSY 1 /* set visible busy */ +#define CLR_BUSY 0 /* clear visible busy */ +#define SET_BUSY 1 /* set visible busy */ /* Command word - <12:8> are opcode, <7:0> are opcode dependent - cold load read <7:6> = head - <5:0> = sector - set file mask <7:4> = retry count - <3:0> = file mask (auto-seek options) - commands with units <7> = hold flag - <4:0> = unit number */ + cold load read <7:6> = head + <5:0> = sector + set file mask <7:4> = retry count + <3:0> = file mask (auto-seek options) + commands with units <7> = hold flag + <4:0> = unit number */ -#define DSC_V_OP 8 /* opcode */ -#define DSC_M_OP 037 -#define DSC_COLD 000 /* cold load read */ -#define DSC_RECAL 001 /* recalibrate */ -#define DSC_SEEK 002 /* seek */ -#define DSC_RSTA 003 /* request status */ -#define DSC_RSA 004 /* request sector addr */ -#define DSC_READ 005 /* read */ -#define DSC_RFULL 006 /* read full */ -#define DSC_VFY 007 /* verify */ -#define DSC_WRITE 010 /* write */ -#define DSC_WFULL 011 /* write full */ -#define DSC_CLEAR 012 /* clear */ -#define DSC_INIT 013 /* initialize */ -#define DSC_AREC 014 /* address record */ -#define DSC_RSYN 015 /* request syndrome */ -#define DSC_ROFF 016 /* read with offset */ -#define DSC_SFM 017 /* set file mask */ -#define DSC_RNOVFY 022 /* read no verify */ -#define DSC_WTIO 023 /* write TIO */ -#define DSC_RDA 024 /* request disk addr */ -#define DSC_END 025 /* end */ -#define DSC_WAKE 026 /* wakeup */ -#define DSC_ATN 035 /* pseudo: ATN */ -#define DSC_BADU 036 /* pseudo: bad unit */ -#define DSC_BADF 037 /* pseudo: bad opcode */ -#define DSC_NEXT 0040 /* state increment */ -#define DSC_2ND 0040 /* subcommand states */ -#define DSC_3RD 0100 -#define DSC_4TH 0140 -#define DSC_V_CHD 6 /* cold load head */ -#define DSC_M_CHD 03 -#define DSC_V_CSC 0 /* cold load sector */ -#define DSC_M_CSC 077 -#define DSC_V_RTY 4 /* retry count */ -#define DSC_M_RTY 017 -#define DSC_V_DECR 3 /* seek decrement */ -#define DSC_V_SPEN 2 /* enable sparing */ -#define DSC_V_CYLM 1 /* cylinder mode */ -#define DSC_V_AUTO 0 /* auto seek */ -#define DSC_V_HOLD 7 /* hold flag */ -#define DSC_V_UNIT 0 /* unit */ -#define DSC_M_UNIT 017 -#define DSC_V_SPAR 15 /* INIT spare */ -#define DSC_V_PROT 14 /* INIT protected */ -#define DSC_V_DFCT 13 /* INIT defective */ +#define DSC_V_OP 8 /* opcode */ +#define DSC_M_OP 037 +#define DSC_COLD 000 /* cold load read */ +#define DSC_RECAL 001 /* recalibrate */ +#define DSC_SEEK 002 /* seek */ +#define DSC_RSTA 003 /* request status */ +#define DSC_RSA 004 /* request sector addr */ +#define DSC_READ 005 /* read */ +#define DSC_RFULL 006 /* read full */ +#define DSC_VFY 007 /* verify */ +#define DSC_WRITE 010 /* write */ +#define DSC_WFULL 011 /* write full */ +#define DSC_CLEAR 012 /* clear */ +#define DSC_INIT 013 /* initialize */ +#define DSC_AREC 014 /* address record */ +#define DSC_RSYN 015 /* request syndrome */ +#define DSC_ROFF 016 /* read with offset */ +#define DSC_SFM 017 /* set file mask */ +#define DSC_RNOVFY 022 /* read no verify */ +#define DSC_WTIO 023 /* write TIO */ +#define DSC_RDA 024 /* request disk addr */ +#define DSC_END 025 /* end */ +#define DSC_WAKE 026 /* wakeup */ +#define DSC_ATN 035 /* pseudo: ATN */ +#define DSC_BADU 036 /* pseudo: bad unit */ +#define DSC_BADF 037 /* pseudo: bad opcode */ +#define DSC_NEXT 0040 /* state increment */ +#define DSC_2ND 0040 /* subcommand states */ +#define DSC_3RD 0100 +#define DSC_4TH 0140 +#define DSC_V_CHD 6 /* cold load head */ +#define DSC_M_CHD 03 +#define DSC_V_CSC 0 /* cold load sector */ +#define DSC_M_CSC 077 +#define DSC_V_RTY 4 /* retry count */ +#define DSC_M_RTY 017 +#define DSC_V_DECR 3 /* seek decrement */ +#define DSC_V_SPEN 2 /* enable sparing */ +#define DSC_V_CYLM 1 /* cylinder mode */ +#define DSC_V_AUTO 0 /* auto seek */ +#define DSC_V_HOLD 7 /* hold flag */ +#define DSC_V_UNIT 0 /* unit */ +#define DSC_M_UNIT 017 +#define DSC_V_SPAR 15 /* INIT spare */ +#define DSC_V_PROT 14 /* INIT protected */ +#define DSC_V_DFCT 13 /* INIT defective */ -#define DSC_HOLD (1u << DSC_V_HOLD) -#define DSC_DECR (1u << DSC_V_DECR) -#define DSC_SPEN (1u << DSC_V_SPEN) -#define DSC_CYLM (1u << DSC_V_CYLM) -#define DSC_AUTO (1u << DSC_V_AUTO) -#define DSC_FMASK ((DSC_M_RTY << DSC_V_RTY)|DSC_DECR|\ - DSC_SPEN|DSC_CYLM|DSC_AUTO) -#define DSC_GETOP(x) (((x) >> DSC_V_OP) & DSC_M_OP) -#define DSC_GETUNIT(x) (((x) >> DSC_V_UNIT) & DSC_M_UNIT) -#define DSC_GETCHD(x) (((x) >> DSC_V_CHD) & DSC_M_CHD) -#define DSC_GETCSC(x) (((x) >> DSC_V_CSC) & DSC_M_CSC) -#define DSC_SPAR (1u << DSC_V_SPAR) -#define DSC_PROT (1u << DSC_V_PROT) -#define DSC_DFCT (1u << DSC_V_DFCT) +#define DSC_HOLD (1u << DSC_V_HOLD) +#define DSC_DECR (1u << DSC_V_DECR) +#define DSC_SPEN (1u << DSC_V_SPEN) +#define DSC_CYLM (1u << DSC_V_CYLM) +#define DSC_AUTO (1u << DSC_V_AUTO) +#define DSC_FMASK ((DSC_M_RTY << DSC_V_RTY)|DSC_DECR|\ + DSC_SPEN|DSC_CYLM|DSC_AUTO) +#define DSC_GETOP(x) (((x) >> DSC_V_OP) & DSC_M_OP) +#define DSC_GETUNIT(x) (((x) >> DSC_V_UNIT) & DSC_M_UNIT) +#define DSC_GETCHD(x) (((x) >> DSC_V_CHD) & DSC_M_CHD) +#define DSC_GETCSC(x) (((x) >> DSC_V_CSC) & DSC_M_CSC) +#define DSC_SPAR (1u << DSC_V_SPAR) +#define DSC_PROT (1u << DSC_V_PROT) +#define DSC_DFCT (1u << DSC_V_DFCT) /* Command flags */ -#define CMF_UNDF 001 /* undefined */ -#define CMF_CLREC 002 /* clear eoc flag */ -#define CMF_CLRS 004 /* clear status */ -#define CMF_UIDLE 010 /* requires unit no */ +#define CMF_UNDF 001 /* undefined */ +#define CMF_CLREC 002 /* clear eoc flag */ +#define CMF_CLRS 004 /* clear status */ +#define CMF_UIDLE 010 /* requires unit no */ /* Cylinder words - 16b */ /* Head/sector word */ -#define DSHS_V_HD 8 /* head */ -#define DSHS_M_HD 037 -#define DSHS_V_SC 0 /* sector */ -#define DSHS_M_SC 0377 -#define DSHS_HD (DSHS_M_HD << DSHS_V_HD) -#define DSHS_SC (DSHS_M_SC << DSHS_V_SC) -#define DSHS_GETHD(x) (((x) >> DSHS_V_HD) & DSHS_M_HD) -#define DSHS_GETSC(x) (((x) >> DSHS_V_SC) & DSHS_M_SC) +#define DSHS_V_HD 8 /* head */ +#define DSHS_M_HD 037 +#define DSHS_V_SC 0 /* sector */ +#define DSHS_M_SC 0377 +#define DSHS_HD (DSHS_M_HD << DSHS_V_HD) +#define DSHS_SC (DSHS_M_SC << DSHS_V_SC) +#define DSHS_GETHD(x) (((x) >> DSHS_V_HD) & DSHS_M_HD) +#define DSHS_GETSC(x) (((x) >> DSHS_V_SC) & DSHS_M_SC) /* Status 1 */ -#define DS1_V_SPAR 15 /* spare - na */ -#define DS1_V_PROT 14 /* protected - na */ -#define DS1_V_DFCT 13 /* defective - na */ -#define DS1_V_STAT 8 /* status */ -#define DS1_OK (000 << DS1_V_STAT) /* normal */ -#define DS1_ILLOP (001 << DS1_V_STAT) /* illegal opcode */ -#define DS1_AVAIL (002 << DS1_V_STAT) /* available */ -#define DS1_CYLCE (007 << DS1_V_STAT) /* cyl compare err */ -#define DS1_UNCOR (010 << DS1_V_STAT) /* uncor data err */ -#define DS1_HSCE (011 << DS1_V_STAT) /* h/s compare err */ -#define DS1_IOPE (012 << DS1_V_STAT) /* IO oper err - na */ -#define DS1_EOCYL (014 << DS1_V_STAT) /* end cylinder */ -#define DS1_OVRUN (016 << DS1_V_STAT) /* overrun */ -#define DS1_CORDE (017 << DS1_V_STAT) /* correctible - na */ -#define DS1_ILLST (020 << DS1_V_STAT) /* illegal spare - na */ -#define DS1_DEFTK (021 << DS1_V_STAT) /* defective trk - na */ -#define DS1_ACCER (022 << DS1_V_STAT) /* access not rdy - na */ -#define DS1_S2ERR (023 << DS1_V_STAT) /* status 2 error */ -#define DS1_TKPER (026 << DS1_V_STAT) /* protected trk - na */ -#define DS1_UNAVL (027 << DS1_V_STAT) /* illegal unit */ -#define DS1_ATN (037 << DS1_V_STAT) /* attention */ -#define DS1_V_UNIT 0 -#define DS1_SPAR (1u << DS1_V_SPAR) -#define DS1_PROT (1u << DS1_V_PROT) -#define DS1_DFCT (1u << DS1_V_DFCT) +#define DS1_V_SPAR 15 /* spare - na */ +#define DS1_V_PROT 14 /* protected - na */ +#define DS1_V_DFCT 13 /* defective - na */ +#define DS1_V_STAT 8 /* status */ +#define DS1_OK (000 << DS1_V_STAT) /* normal */ +#define DS1_ILLOP (001 << DS1_V_STAT) /* illegal opcode */ +#define DS1_AVAIL (002 << DS1_V_STAT) /* available */ +#define DS1_CYLCE (007 << DS1_V_STAT) /* cyl compare err */ +#define DS1_UNCOR (010 << DS1_V_STAT) /* uncor data err */ +#define DS1_HSCE (011 << DS1_V_STAT) /* h/s compare err */ +#define DS1_IOPE (012 << DS1_V_STAT) /* IO oper err - na */ +#define DS1_EOCYL (014 << DS1_V_STAT) /* end cylinder */ +#define DS1_OVRUN (016 << DS1_V_STAT) /* overrun */ +#define DS1_CORDE (017 << DS1_V_STAT) /* correctible - na */ +#define DS1_ILLST (020 << DS1_V_STAT) /* illegal spare - na */ +#define DS1_DEFTK (021 << DS1_V_STAT) /* defective trk - na */ +#define DS1_ACCER (022 << DS1_V_STAT) /* access not rdy - na */ +#define DS1_S2ERR (023 << DS1_V_STAT) /* status 2 error */ +#define DS1_TKPER (026 << DS1_V_STAT) /* protected trk - na */ +#define DS1_UNAVL (027 << DS1_V_STAT) /* illegal unit */ +#define DS1_ATN (037 << DS1_V_STAT) /* attention */ +#define DS1_V_UNIT 0 +#define DS1_SPAR (1u << DS1_V_SPAR) +#define DS1_PROT (1u << DS1_V_PROT) +#define DS1_DFCT (1u << DS1_V_DFCT) /* Status 2, ^ = kept in unit status, * = dynamic */ -#define DS2_ERR 0100000 /* *error */ -#define DS2_V_ID 9 /* drive type */ -#define DS2_ATN 0000200 /* ^attention */ -#define DS2_RO 0000100 /* *read only */ -#define DS2_FRM 0000040 /* *format */ -#define DS2_FLT 0000020 /* fault - na */ -#define DS2_FS 0000010 /* ^first status */ -#define DS2_SC 0000004 /* ^seek error */ -#define DS2_NR 0000002 /* *not ready */ -#define DS2_BS 0000001 /* *busy */ -#define DS2_ALLERR (DS2_FLT|DS2_SC|DS2_NR|DS2_BS) +#define DS2_ERR 0100000 /* *error */ +#define DS2_V_ID 9 /* drive type */ +#define DS2_ATN 0000200 /* ^attention */ +#define DS2_RO 0000100 /* *read only */ +#define DS2_FRM 0000040 /* *format */ +#define DS2_FLT 0000020 /* fault - na */ +#define DS2_FS 0000010 /* ^first status */ +#define DS2_SC 0000004 /* ^seek error */ +#define DS2_NR 0000002 /* *not ready */ +#define DS2_BS 0000001 /* *busy */ +#define DS2_ALLERR (DS2_FLT|DS2_SC|DS2_NR|DS2_BS) /* Controller state */ -#define DS_IDLE 0 /* idle */ -#define DS_WAIT 1 /* command wait */ -#define DS_BUSY 2 /* busy */ - +#define DS_IDLE 0 /* idle */ +#define DS_WAIT 1 /* command wait */ +#define DS_BUSY 2 /* busy */ + /* This controller supports four different disk drive types: - type #sectors/ #surfaces/ #cylinders/ - surface cylinder drive + type #sectors/ #surfaces/ #cylinders/ + surface cylinder drive - 7905 48 3 411 =15MB - 7906 48 4 411 =20MB - 7920 48 5 823 =50MB - 7925 64 9 823 =120MB + 7905 48 3 411 =15MB + 7906 48 4 411 =20MB + 7920 48 5 823 =50MB + 7925 64 9 823 =120MB 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 @@ -279,128 +279,130 @@ */ #define GET_DA(x,y,z,t) \ - (((((y) < drv_tab[t].rh)? \ - (x) * drv_tab[t].rh + (y): \ - drv_tab[t].cyl * drv_tab[t].rh + \ - ((x) * drv_tab[t].fh + (y) - drv_tab[t].rh)) * \ - drv_tab[t].sc + (z)) * DS_NUMWD) + (((((y) < drv_tab[t].rh)? \ + (x) * drv_tab[t].rh + (y): \ + drv_tab[t].cyl * drv_tab[t].rh + \ + ((x) * drv_tab[t].fh + (y) - drv_tab[t].rh)) * \ + drv_tab[t].sc + (z)) * DS_NUMWD) -#define D7905_DTYPE 0 -#define D7905_SECT 48 -#define D7905_SURF 3 -#define D7905_RH 2 -#define D7905_FH (D7905_SURF - D7905_RH) -#define D7905_CYL 411 -#define D7905_ID (2 << DS2_V_ID) -#define D7905_SIZE (D7905_SECT * D7905_SURF * D7905_CYL * DS_NUMWD) +#define D7905_DTYPE 0 +#define D7905_SECT 48 +#define D7905_SURF 3 +#define D7905_RH 2 +#define D7905_FH (D7905_SURF - D7905_RH) +#define D7905_CYL 411 +#define D7905_ID (2 << DS2_V_ID) +#define D7905_SIZE (D7905_SECT * D7905_SURF * D7905_CYL * DS_NUMWD) -#define D7906_DTYPE 1 -#define D7906_SECT 48 -#define D7906_SURF 4 -#define D7906_RH 2 -#define D7906_FH (D7906_SURF - D7906_RH) -#define D7906_CYL 411 -#define D7906_ID (0 << DS2_V_ID) -#define D7906_SIZE (D7906_SECT * D7906_SURF * D7906_CYL * DS_NUMWD) +#define D7906_DTYPE 1 +#define D7906_SECT 48 +#define D7906_SURF 4 +#define D7906_RH 2 +#define D7906_FH (D7906_SURF - D7906_RH) +#define D7906_CYL 411 +#define D7906_ID (0 << DS2_V_ID) +#define D7906_SIZE (D7906_SECT * D7906_SURF * D7906_CYL * DS_NUMWD) -#define D7920_DTYPE 2 -#define D7920_SECT 48 -#define D7920_SURF 5 -#define D7920_RH D7920_SURF -#define D7920_FH (D7920_SURF - D7920_RH) -#define D7920_CYL 823 -#define D7920_ID (1 << DS2_V_ID) -#define D7920_SIZE (D7920_SECT * D7920_SURF * D7920_CYL * DS_NUMWD) +#define D7920_DTYPE 2 +#define D7920_SECT 48 +#define D7920_SURF 5 +#define D7920_RH D7920_SURF +#define D7920_FH (D7920_SURF - D7920_RH) +#define D7920_CYL 823 +#define D7920_ID (1 << DS2_V_ID) +#define D7920_SIZE (D7920_SECT * D7920_SURF * D7920_CYL * DS_NUMWD) -#define D7925_DTYPE 3 -#define D7925_SECT 64 -#define D7925_SURF 9 -#define D7925_RH D7925_SURF -#define D7925_FH (D7925_SURF - D7925_RH) -#define D7925_CYL 823 -#define D7925_ID (3 << DS2_V_ID) -#define D7925_SIZE (D7925_SECT * D7925_SURF * D7925_CYL * DS_NUMWD) +#define D7925_DTYPE 3 +#define D7925_SECT 64 +#define D7925_SURF 9 +#define D7925_RH D7925_SURF +#define D7925_FH (D7925_SURF - D7925_RH) +#define D7925_CYL 823 +#define D7925_ID (3 << DS2_V_ID) +#define D7925_SIZE (D7925_SECT * D7925_SURF * D7925_CYL * DS_NUMWD) struct drvtyp { - uint32 sc; /* sectors */ - uint32 hd; /* surfaces */ - uint32 cyl; /* cylinders */ - uint32 size; /* #blocks */ - uint32 id; /* device type */ - uint32 rh; /* removable surfaces */ - uint32 fh; /* fixed surfaces */ -}; + uint32 sc; /* sectors */ + uint32 hd; /* surfaces */ + uint32 cyl; /* cylinders */ + uint32 size; /* #blocks */ + uint32 id; /* device type */ + uint32 rh; /* removable surfaces */ + uint32 fh; /* fixed surfaces */ + }; static struct drvtyp drv_tab[] = { - { D7905_SECT, D7905_SURF, D7905_CYL, D7905_SIZE, D7905_ID, D7905_RH, D7905_FH }, - { D7906_SECT, D7906_SURF, D7906_CYL, D7906_SIZE, D7906_ID, D7906_RH, D7906_FH }, - { D7920_SECT, D7920_SURF, D7920_CYL, D7920_SIZE, D7920_ID, D7920_RH, D7920_FH }, - { D7925_SECT, D7925_SURF, D7925_CYL, D7925_SIZE, D7925_ID, D7925_RH, D7925_FH }, - { 0 } }; - + { D7905_SECT, D7905_SURF, D7905_CYL, D7905_SIZE, D7905_ID, D7905_RH, D7905_FH }, + { D7906_SECT, D7906_SURF, D7906_CYL, D7906_SIZE, D7906_ID, D7906_RH, D7906_FH }, + { D7920_SECT, D7920_SURF, D7920_CYL, D7920_SIZE, D7920_ID, D7920_RH, D7920_FH }, + { D7925_SECT, D7925_SURF, D7925_CYL, D7925_SIZE, D7925_ID, D7925_RH, D7925_FH }, + { 0 } + }; + extern uint32 PC, SR; extern uint32 dev_cmd[2], dev_ctl[2], dev_flg[2], dev_fbf[2], dev_srq[2]; extern int32 sim_switches; extern UNIT cpu_unit; -uint32 ds_fifo[DS_FIFO_SIZE] = { 0 }; /* fifo */ -uint32 ds_fifo_ip = 0; /* insertion ptr */ -uint32 ds_fifo_rp = 0; /* removal ptr */ -uint32 ds_fifo_cnt = 0; /* count */ -uint32 ds_cmd = 0; /* command word */ -uint32 ds_sr1 = 0; /* status word 1 */ -uint32 ds_busy = 0; /* busy flag */ -uint32 ds_eoc = 0; /* end of cylinder */ -uint32 ds_eod = 0; /* end of data */ -uint32 ds_fmask = 0; /* file mask */ -uint32 ds_cmdf = 0; /* command follows */ -uint32 ds_cmdp = 0; /* command present */ -uint32 ds_cyl = 0; /* disk address: cyl */ -uint32 ds_hs = 0; /* disk address: hs */ -uint32 ds_vctr = 0; /* verify counter */ -uint32 ds_state = 0; /* controller state */ -uint32 ds_lastatn = 0; /* last atn intr */ -int32 ds_stime = 100; /* seek time */ -int32 ds_rtime = 100; /* inter-sector time */ -int32 ds_ctime = 3; /* command time */ -int32 ds_dtime = 1; /* dch time */ -int32 ds_tmo = 2749200; /* timeout = 1.74 sec */ -uint32 ds_ptr = 0; /* buffer ptr */ -uint16 dsxb[DS_NUMWDF]; /* sector buffer */ +uint32 ds_fifo[DS_FIFO_SIZE] = { 0 }; /* fifo */ +uint32 ds_fifo_ip = 0; /* insertion ptr */ +uint32 ds_fifo_rp = 0; /* removal ptr */ +uint32 ds_fifo_cnt = 0; /* count */ +uint32 ds_cmd = 0; /* command word */ +uint32 ds_sr1 = 0; /* status word 1 */ +uint32 ds_busy = 0; /* busy flag */ +uint32 ds_eoc = 0; /* end of cylinder */ +uint32 ds_eod = 0; /* end of data */ +uint32 ds_fmask = 0; /* file mask */ +uint32 ds_cmdf = 0; /* command follows */ +uint32 ds_cmdp = 0; /* command present */ +uint32 ds_cyl = 0; /* disk address: cyl */ +uint32 ds_hs = 0; /* disk address: hs */ +uint32 ds_vctr = 0; /* verify counter */ +uint32 ds_state = 0; /* controller state */ +uint32 ds_lastatn = 0; /* last atn intr */ +int32 ds_stime = 100; /* seek time */ +int32 ds_rtime = 100; /* inter-sector time */ +int32 ds_ctime = 3; /* command time */ +int32 ds_dtime = 1; /* dch time */ +int32 ds_tmo = 2749200; /* timeout = 1.74 sec */ +uint32 ds_ptr = 0; /* buffer ptr */ +uint16 dsxb[DS_NUMWDF]; /* sector buffer */ -static const uint32 ds_opflags[32] = { /* flags for ops */ - CMF_CLREC|CMF_CLRS|CMF_UIDLE, /* cold read */ - CMF_CLREC|CMF_CLRS|CMF_UIDLE, /* recalibrate */ - CMF_CLREC|CMF_CLRS|CMF_UIDLE, /* seek */ - 0, /* read status */ - CMF_CLRS, /* read sector */ - CMF_CLRS|CMF_UIDLE, /* read */ - CMF_CLRS|CMF_UIDLE, /* read full */ - CMF_CLRS|CMF_UIDLE, /* verify */ - CMF_CLRS|CMF_UIDLE, /* write */ - CMF_CLRS|CMF_UIDLE, /* write full */ - CMF_CLRS, /* clear */ - CMF_CLRS|CMF_UIDLE, /* init */ - CMF_CLREC|CMF_CLRS, /* addr record */ - 0, /* read syndrome */ - CMF_CLRS|CMF_UIDLE, /* read offset */ - CMF_CLRS, /* set file mask */ - CMF_UNDF|CMF_CLRS, /* undefined */ - CMF_UNDF|CMF_CLRS, /* undefined */ - CMF_CLRS|CMF_UIDLE, /* read no verify */ - CMF_CLRS, /* write TIO */ - CMF_CLRS, /* read disk addr */ - CMF_CLRS, /* end */ - CMF_CLRS, /* wake */ - CMF_UNDF|CMF_CLRS, /* undefined */ - CMF_UNDF|CMF_CLRS, /* undefined */ - CMF_UNDF|CMF_CLRS, /* undefined */ - CMF_UNDF|CMF_CLRS, /* undefined */ - CMF_UNDF|CMF_CLRS, /* undefined */ - CMF_UNDF|CMF_CLRS, /* undefined */ - CMF_UNDF|CMF_CLRS, /* undefined */ - CMF_UNDF|CMF_CLRS, /* undefined */ - CMF_UNDF|CMF_CLRS, }; /* undefined */ +static const uint32 ds_opflags[32] = { /* flags for ops */ + CMF_CLREC|CMF_CLRS|CMF_UIDLE, /* cold read */ + CMF_CLREC|CMF_CLRS|CMF_UIDLE, /* recalibrate */ + CMF_CLREC|CMF_CLRS|CMF_UIDLE, /* seek */ + 0, /* read status */ + CMF_CLRS, /* read sector */ + CMF_CLRS|CMF_UIDLE, /* read */ + CMF_CLRS|CMF_UIDLE, /* read full */ + CMF_CLRS|CMF_UIDLE, /* verify */ + CMF_CLRS|CMF_UIDLE, /* write */ + CMF_CLRS|CMF_UIDLE, /* write full */ + CMF_CLRS, /* clear */ + CMF_CLRS|CMF_UIDLE, /* init */ + CMF_CLREC|CMF_CLRS, /* addr record */ + 0, /* read syndrome */ + CMF_CLRS|CMF_UIDLE, /* read offset */ + CMF_CLRS, /* set file mask */ + CMF_UNDF|CMF_CLRS, /* undefined */ + CMF_UNDF|CMF_CLRS, /* undefined */ + CMF_CLRS|CMF_UIDLE, /* read no verify */ + CMF_CLRS, /* write TIO */ + CMF_CLRS, /* read disk addr */ + CMF_CLRS, /* end */ + CMF_CLRS, /* wake */ + CMF_UNDF|CMF_CLRS, /* undefined */ + CMF_UNDF|CMF_CLRS, /* undefined */ + CMF_UNDF|CMF_CLRS, /* undefined */ + CMF_UNDF|CMF_CLRS, /* undefined */ + CMF_UNDF|CMF_CLRS, /* undefined */ + CMF_UNDF|CMF_CLRS, /* undefined */ + CMF_UNDF|CMF_CLRS, /* undefined */ + CMF_UNDF|CMF_CLRS, /* undefined */ + CMF_UNDF|CMF_CLRS /* undefined */ + }; DEVICE ds_dev; int32 dsio (int32 inst, int32 IR, int32 dat); @@ -437,178 +439,193 @@ void ds_sched_atn (UNIT *uptr); uint32 ds_fifo_read (void); void ds_fifo_write (uint32 dat); void ds_fifo_reset (void); - + /* DS data structures - ds_dev DS device descriptor - ds_unit DS unit list - ds_reg DS register list - ds_mod DS modifier list + ds_dev DS device descriptor + ds_unit DS unit list + ds_reg DS register list + ds_mod DS modifier list */ DIB ds_dib = { DS, 0, 0, 0, 0, 0, &dsio }; UNIT ds_unit[] = { - { UDATA (&ds_svc_u, UNIT_FIX | UNIT_ATTABLE | UNIT_ROABLE | - UNIT_DISABLE | UNIT_UNLOAD, D7905_SIZE) }, - { UDATA (&ds_svc_u, UNIT_FIX | UNIT_ATTABLE | UNIT_ROABLE | - UNIT_DISABLE | UNIT_UNLOAD, D7905_SIZE) }, - { UDATA (&ds_svc_u, UNIT_FIX | UNIT_ATTABLE | UNIT_ROABLE | - UNIT_DISABLE | UNIT_UNLOAD, D7905_SIZE) }, - { UDATA (&ds_svc_u, UNIT_FIX | UNIT_ATTABLE | UNIT_ROABLE | - UNIT_DISABLE | UNIT_UNLOAD, D7905_SIZE) }, - { UDATA (&ds_svc_u, UNIT_FIX | UNIT_ATTABLE | UNIT_ROABLE | - UNIT_DISABLE | UNIT_UNLOAD, D7905_SIZE) }, - { UDATA (&ds_svc_u, UNIT_FIX | UNIT_ATTABLE | UNIT_ROABLE | - UNIT_DISABLE | UNIT_UNLOAD, D7905_SIZE) }, - { UDATA (&ds_svc_u, UNIT_FIX | UNIT_ATTABLE | UNIT_ROABLE | - UNIT_DISABLE | UNIT_UNLOAD, D7905_SIZE) }, - { UDATA (&ds_svc_u, UNIT_FIX | UNIT_ATTABLE | UNIT_ROABLE | - UNIT_DISABLE | UNIT_UNLOAD, D7905_SIZE) }, - { UDATA (&ds_svc_c, UNIT_DIS, 0) }, - { UDATA (&ds_svc_t, UNIT_DIS, 0) } }; + { UDATA (&ds_svc_u, UNIT_FIX | UNIT_ATTABLE | UNIT_ROABLE | + UNIT_DISABLE | UNIT_UNLOAD, D7905_SIZE) }, + { UDATA (&ds_svc_u, UNIT_FIX | UNIT_ATTABLE | UNIT_ROABLE | + UNIT_DISABLE | UNIT_UNLOAD, D7905_SIZE) }, + { UDATA (&ds_svc_u, UNIT_FIX | UNIT_ATTABLE | UNIT_ROABLE | + UNIT_DISABLE | UNIT_UNLOAD, D7905_SIZE) }, + { UDATA (&ds_svc_u, UNIT_FIX | UNIT_ATTABLE | UNIT_ROABLE | + UNIT_DISABLE | UNIT_UNLOAD, D7905_SIZE) }, + { UDATA (&ds_svc_u, UNIT_FIX | UNIT_ATTABLE | UNIT_ROABLE | + UNIT_DISABLE | UNIT_UNLOAD, D7905_SIZE) }, + { UDATA (&ds_svc_u, UNIT_FIX | UNIT_ATTABLE | UNIT_ROABLE | + UNIT_DISABLE | UNIT_UNLOAD, D7905_SIZE) }, + { UDATA (&ds_svc_u, UNIT_FIX | UNIT_ATTABLE | UNIT_ROABLE | + UNIT_DISABLE | UNIT_UNLOAD, D7905_SIZE) }, + { UDATA (&ds_svc_u, UNIT_FIX | UNIT_ATTABLE | UNIT_ROABLE | + UNIT_DISABLE | UNIT_UNLOAD, D7905_SIZE) }, + { UDATA (&ds_svc_c, UNIT_DIS, 0) }, + { UDATA (&ds_svc_t, UNIT_DIS, 0) } + }; REG ds_reg[] = { - { ORDATA (CMD, ds_cmd, 16) }, - { BRDATA (FIFO, ds_fifo, 8, 16, DS_FIFO_SIZE) }, - { ORDATA (SR1, ds_sr1, 16) }, - { ORDATA (VCTR, ds_vctr, 16) }, - { ORDATA (FMASK, ds_fmask, 8) }, - { ORDATA (CYL, ds_cyl, 16) }, - { ORDATA (HS, ds_hs, 16) }, - { ORDATA (STATE, ds_state, 2), REG_RO }, - { ORDATA (LASTA, ds_lastatn, 3) }, - { DRDATA (FIP, ds_fifo_ip, 4) }, - { DRDATA (FRP, ds_fifo_rp, 4) }, - { DRDATA (FCNT, ds_fifo_cnt, 5) }, - { FLDATA (CMD, ds_dib.cmd, 0), REG_HRO }, - { FLDATA (CTL, ds_dib.ctl, 0) }, - { FLDATA (FLG, ds_dib.flg, 0) }, - { FLDATA (FBF, ds_dib.fbf, 0) }, - { FLDATA (SRQ, ds_dib.srq, 0) }, - { FLDATA (BUSY, ds_busy, 0) }, - { FLDATA (CMDF, ds_cmdf, 0) }, - { FLDATA (CMDP, ds_cmdp, 0) }, - { FLDATA (EOC, ds_eoc, 0) }, - { FLDATA (EOD, ds_eod, 0) }, - { BRDATA (DBUF, dsxb, 8, 16, DS_NUMWDF) }, - { FLDATA (DPTR, ds_ptr, 8) }, - { DRDATA (CTIME, ds_ctime, 24), PV_LEFT + REG_NZ }, - { DRDATA (DTIME, ds_dtime, 24), PV_LEFT + REG_NZ }, - { DRDATA (STIME, ds_stime, 24), PV_LEFT + REG_NZ }, - { DRDATA (RTIME, ds_rtime, 24), PV_LEFT + REG_NZ }, - { DRDATA (TIMEOUT, ds_tmo, 31), PV_LEFT + REG_NZ }, - { URDATA (UCYL, ds_unit[0].CYL, 10, 10, 0, - DS_NUMDR + 1, PV_LEFT | REG_HRO) }, - { URDATA (UFNC, ds_unit[0].FNC, 8, 8, 0, - DS_NUMDR + 1, REG_HRO) }, - { URDATA (USTA, ds_unit[0].STA, 8, 16, 0, - DS_NUMDR + 1, REG_HRO) }, - { URDATA (CAPAC, ds_unit[0].capac, 10, T_ADDR_W, 0, - DS_NUMDR, PV_LEFT | REG_HRO) }, - { ORDATA (DEVNO, ds_dib.devno, 6), REG_HRO }, - { NULL } }; + { ORDATA (CMD, ds_cmd, 16) }, + { BRDATA (FIFO, ds_fifo, 8, 16, DS_FIFO_SIZE) }, + { ORDATA (SR1, ds_sr1, 16) }, + { ORDATA (VCTR, ds_vctr, 16) }, + { ORDATA (FMASK, ds_fmask, 8) }, + { ORDATA (CYL, ds_cyl, 16) }, + { ORDATA (HS, ds_hs, 16) }, + { ORDATA (STATE, ds_state, 2), REG_RO }, + { ORDATA (LASTA, ds_lastatn, 3) }, + { DRDATA (FIP, ds_fifo_ip, 4) }, + { DRDATA (FRP, ds_fifo_rp, 4) }, + { DRDATA (FCNT, ds_fifo_cnt, 5) }, + { FLDATA (CMD, ds_dib.cmd, 0), REG_HRO }, + { FLDATA (CTL, ds_dib.ctl, 0) }, + { FLDATA (FLG, ds_dib.flg, 0) }, + { FLDATA (FBF, ds_dib.fbf, 0) }, + { FLDATA (SRQ, ds_dib.srq, 0) }, + { FLDATA (BUSY, ds_busy, 0) }, + { FLDATA (CMDF, ds_cmdf, 0) }, + { FLDATA (CMDP, ds_cmdp, 0) }, + { FLDATA (EOC, ds_eoc, 0) }, + { FLDATA (EOD, ds_eod, 0) }, + { BRDATA (DBUF, dsxb, 8, 16, DS_NUMWDF) }, + { FLDATA (DPTR, ds_ptr, 8) }, + { DRDATA (CTIME, ds_ctime, 24), PV_LEFT + REG_NZ }, + { DRDATA (DTIME, ds_dtime, 24), PV_LEFT + REG_NZ }, + { DRDATA (STIME, ds_stime, 24), PV_LEFT + REG_NZ }, + { DRDATA (RTIME, ds_rtime, 24), PV_LEFT + REG_NZ }, + { DRDATA (TIMEOUT, ds_tmo, 31), PV_LEFT + REG_NZ }, + { URDATA (UCYL, ds_unit[0].CYL, 10, 10, 0, + DS_NUMDR + 1, PV_LEFT | REG_HRO) }, + { URDATA (UFNC, ds_unit[0].FNC, 8, 8, 0, + DS_NUMDR + 1, REG_HRO) }, + { URDATA (USTA, ds_unit[0].STA, 8, 16, 0, + DS_NUMDR + 1, REG_HRO) }, + { URDATA (CAPAC, ds_unit[0].capac, 10, T_ADDR_W, 0, + DS_NUMDR, PV_LEFT | REG_HRO) }, + { ORDATA (DEVNO, ds_dib.devno, 6), REG_HRO }, + { NULL } + }; MTAB ds_mod[] = { - { UNIT_UNLOAD, UNIT_UNLOAD, "heads unloaded", "UNLOADED", ds_load_unload }, - { UNIT_UNLOAD, 0, "heads loaded", "LOADED", ds_load_unload }, - { UNIT_WLK, 0, "write enabled", "WRITEENABLED", NULL }, - { UNIT_WLK, UNIT_WLK, "write locked", "LOCKED", NULL }, - { UNIT_FMT, 0, "format disabled", "NOFORMAT", NULL }, - { UNIT_FMT, UNIT_FMT, "format enabled", "FORMAT", NULL }, - { (UNIT_DTYPE+UNIT_ATT), (D7905_DTYPE << UNIT_V_DTYPE) + UNIT_ATT, - "7905", NULL, NULL }, - { (UNIT_DTYPE+UNIT_ATT), (D7906_DTYPE << UNIT_V_DTYPE) + UNIT_ATT, - "7906", NULL, NULL }, - { (UNIT_DTYPE+UNIT_ATT), (D7920_DTYPE << UNIT_V_DTYPE) + UNIT_ATT, - "7920", NULL, NULL }, - { (UNIT_DTYPE+UNIT_ATT), (D7925_DTYPE << UNIT_V_DTYPE) + UNIT_ATT, - "7925", NULL, NULL }, - { (UNIT_AUTO+UNIT_DTYPE+UNIT_ATT), (D7905_DTYPE << UNIT_V_DTYPE), - "7905", NULL, NULL }, - { (UNIT_AUTO+UNIT_DTYPE+UNIT_ATT), (D7906_DTYPE << UNIT_V_DTYPE), - "7906", NULL, NULL }, - { (UNIT_AUTO+UNIT_DTYPE+UNIT_ATT), (D7920_DTYPE << UNIT_V_DTYPE), - "7920", NULL, NULL }, - { (UNIT_AUTO+UNIT_DTYPE+UNIT_ATT), (D7925_DTYPE << UNIT_V_DTYPE), - "7925", NULL, NULL }, - { (UNIT_AUTO+UNIT_ATT), UNIT_AUTO, "autosize", NULL, NULL }, - { UNIT_AUTO, UNIT_AUTO, NULL, "AUTOSIZE", NULL }, - { (UNIT_AUTO+UNIT_DTYPE), (D7905_DTYPE << UNIT_V_DTYPE), - NULL, "7905", &ds_set_size }, - { (UNIT_AUTO+UNIT_DTYPE), (D7906_DTYPE << UNIT_V_DTYPE), - NULL, "7906", &ds_set_size }, - { (UNIT_AUTO+UNIT_DTYPE), (D7920_DTYPE << UNIT_V_DTYPE), - NULL, "7920", &ds_set_size }, - { (UNIT_AUTO+UNIT_DTYPE), (D7925_DTYPE << UNIT_V_DTYPE), - NULL, "7925", &ds_set_size }, - { MTAB_XTD | MTAB_VDV, 0, "DEVNO", "DEVNO", - &hp_setdev, &hp_showdev, &ds_dev }, - { 0 } }; + { UNIT_UNLOAD, UNIT_UNLOAD, "heads unloaded", "UNLOADED", ds_load_unload }, + { UNIT_UNLOAD, 0, "heads loaded", "LOADED", ds_load_unload }, + { UNIT_WLK, 0, "write enabled", "WRITEENABLED", NULL }, + { UNIT_WLK, UNIT_WLK, "write locked", "LOCKED", NULL }, + { UNIT_FMT, 0, "format disabled", "NOFORMAT", NULL }, + { UNIT_FMT, UNIT_FMT, "format enabled", "FORMAT", NULL }, + { (UNIT_DTYPE+UNIT_ATT), (D7905_DTYPE << UNIT_V_DTYPE) + UNIT_ATT, + "7905", NULL, NULL }, + { (UNIT_DTYPE+UNIT_ATT), (D7906_DTYPE << UNIT_V_DTYPE) + UNIT_ATT, + "7906", NULL, NULL }, + { (UNIT_DTYPE+UNIT_ATT), (D7920_DTYPE << UNIT_V_DTYPE) + UNIT_ATT, + "7920", NULL, NULL }, + { (UNIT_DTYPE+UNIT_ATT), (D7925_DTYPE << UNIT_V_DTYPE) + UNIT_ATT, + "7925", NULL, NULL }, + { (UNIT_AUTO+UNIT_DTYPE+UNIT_ATT), (D7905_DTYPE << UNIT_V_DTYPE), + "7905", NULL, NULL }, + { (UNIT_AUTO+UNIT_DTYPE+UNIT_ATT), (D7906_DTYPE << UNIT_V_DTYPE), + "7906", NULL, NULL }, + { (UNIT_AUTO+UNIT_DTYPE+UNIT_ATT), (D7920_DTYPE << UNIT_V_DTYPE), + "7920", NULL, NULL }, + { (UNIT_AUTO+UNIT_DTYPE+UNIT_ATT), (D7925_DTYPE << UNIT_V_DTYPE), + "7925", NULL, NULL }, + { (UNIT_AUTO+UNIT_ATT), UNIT_AUTO, "autosize", NULL, NULL }, + { UNIT_AUTO, UNIT_AUTO, NULL, "AUTOSIZE", NULL }, + { (UNIT_AUTO+UNIT_DTYPE), (D7905_DTYPE << UNIT_V_DTYPE), + NULL, "7905", &ds_set_size }, + { (UNIT_AUTO+UNIT_DTYPE), (D7906_DTYPE << UNIT_V_DTYPE), + NULL, "7906", &ds_set_size }, + { (UNIT_AUTO+UNIT_DTYPE), (D7920_DTYPE << UNIT_V_DTYPE), + NULL, "7920", &ds_set_size }, + { (UNIT_AUTO+UNIT_DTYPE), (D7925_DTYPE << UNIT_V_DTYPE), + NULL, "7925", &ds_set_size }, + { MTAB_XTD | MTAB_VDV, 0, "DEVNO", "DEVNO", + &hp_setdev, &hp_showdev, &ds_dev }, + { 0 } + }; DEVICE ds_dev = { - "DS", ds_unit, ds_reg, ds_mod, - DS_NUMDR + 2, 8, 27, 1, 8, 16, - NULL, NULL, &ds_reset, - &ds_boot, &ds_attach, &ds_detach, - &ds_dib, DEV_DISABLE }; - + "DS", ds_unit, ds_reg, ds_mod, + DS_NUMDR + 2, 8, 27, 1, 8, 16, + NULL, NULL, &ds_reset, + &ds_boot, &ds_attach, &ds_detach, + &ds_dib, DEV_DISABLE + }; + /* IO instructions */ int32 dsio (int32 inst, int32 IR, int32 dat) { uint32 dev = IR & I_DEVMASK; -switch (inst) { /* case on opcode */ -case ioFLG: /* flag clear/set */ - if ((IR & I_HC) == 0) { setFLG (dev); } /* STF */ - break; -case ioSFS: /* skip flag set */ - if (FLG (dev) != 0) PC = (PC + 1) & VAMASK; - break; -case ioSFC: /* skip flag clear */ - if (ds_busy == 0) PC = (PC + 1) & VAMASK; - break; -case ioOTX: /* output */ - if (ds_cmdf) { /* expecting command? */ - ds_cmd = dat; /* save command */ - ds_cmdf = 0; - ds_cmdp = 1; /* command present */ - } - else ds_fifo_write (dat); /* put in fifo */ - break; -case ioMIX: /* merge */ - dat = dat | ds_fifo_read (); - break; -case ioLIX: /* load */ - dat = ds_fifo_read (); - break; -case ioCTL: /* control clear/set */ - if (IR & I_CTL) { /* CLC */ - clrCTL (dev); /* clear control */ - ds_cmdf = 1; /* expecting command */ - ds_cmdp = 0; /* none pending */ - ds_fifo_reset (); /* clear fifo */ - } - else { /* STC */ - setCTL (dev); /* set ctl */ - } - break; -case ioEDT: /* end of transfer */ - ds_eod = 1; /* flag end transfer */ - break; -default: - break; } -if (IR & I_HC) { clrFSR (dev); } /* H/C option */ -ds_poll (); /* run the controller */ +switch (inst) { /* case on opcode */ + + case ioFLG: /* flag clear/set */ + if ((IR & I_HC) == 0) { setFLG (dev); } /* STF */ + break; + + case ioSFS: /* skip flag set */ + if (FLG (dev) != 0) PC = (PC + 1) & VAMASK; + break; + + case ioSFC: /* skip flag clear */ + if (ds_busy == 0) PC = (PC + 1) & VAMASK; + break; + + case ioOTX: /* output */ + if (ds_cmdf) { /* expecting command? */ + ds_cmd = dat; /* save command */ + ds_cmdf = 0; + ds_cmdp = 1; /* command present */ + } + else ds_fifo_write (dat); /* put in fifo */ + break; + + case ioMIX: /* merge */ + dat = dat | ds_fifo_read (); + break; + + case ioLIX: /* load */ + dat = ds_fifo_read (); + break; + + case ioCTL: /* control clear/set */ + if (IR & I_CTL) { /* CLC */ + clrCTL (dev); /* clear control */ + ds_cmdf = 1; /* expecting command */ + ds_cmdp = 0; /* none pending */ + ds_fifo_reset (); /* clear fifo */ + } + else { /* STC */ + setCTL (dev); /* set ctl */ + } + break; + + case ioEDT: /* end of transfer */ + ds_eod = 1; /* flag end transfer */ + break; + + default: + break; + } + +if (IR & I_HC) { clrFSR (dev); } /* H/C option */ +ds_poll (); /* run the controller */ return dat; } - + /* Run the controller polling loop, based on ds_state: - IDLE commands and ATN interrupts - WAIT commands only - BUSY nothing + IDLE commands and ATN interrupts + WAIT commands only + BUSY nothing */ void ds_poll (void) @@ -616,7 +633,7 @@ void ds_poll (void) int32 dev = ds_dib.devno; if ((ds_state != DS_BUSY) && ds_cmdp) ds_docmd (ds_cmd);/* cmd pending? */ -if ((ds_state == DS_IDLE) && CTL (dev)) ds_doatn (); /* idle? check ATN */ +if ((ds_state == DS_IDLE) && CTL (dev)) ds_doatn (); /* idle? check ATN */ return; } @@ -633,99 +650,103 @@ void ds_docmd (uint32 cmd) { uint32 op, f, dtyp, unum; -op = DSC_GETOP (cmd); /* operation */ -f = ds_opflags[op]; /* flags */ -if (op == DSC_COLD) unum = 0; /* boot force unit 0 */ -else unum = DSC_GETUNIT (cmd); /* get unit */ -if ((f & CMF_UIDLE) && (unum < DS_NUMDR) && /* idle required */ - sim_is_active (&ds_unit[unum])) { /* but unit busy? */ - ds_state = DS_WAIT; /* wait */ - return; - } -ds_cmdp = 0; /* flush command */ -ds_state = DS_BUSY; /* ctrl is busy */ -if (f & CMF_CLRS) ds_sr1 = 0; /* clear status */ -if (f & CMF_CLREC) ds_eoc = 0; /* clear end cyl */ -if (f & CMF_UNDF) { /* illegal op? */ - ds_sched_ctrl_op (DSC_BADF, 0, CLR_BUSY); /* sched, clr busy */ - return; - } +op = DSC_GETOP (cmd); /* operation */ +f = ds_opflags[op]; /* flags */ +if (op == DSC_COLD) unum = 0; /* boot force unit 0 */ +else unum = DSC_GETUNIT (cmd); /* get unit */ +if ((f & CMF_UIDLE) && (unum < DS_NUMDR) && /* idle required */ + sim_is_active (&ds_unit[unum])) { /* but unit busy? */ + ds_state = DS_WAIT; /* wait */ + return; + } +ds_cmdp = 0; /* flush command */ +ds_state = DS_BUSY; /* ctrl is busy */ +if (f & CMF_CLRS) ds_sr1 = 0; /* clear status */ +if (f & CMF_CLREC) ds_eoc = 0; /* clear end cyl */ +if (f & CMF_UNDF) { /* illegal op? */ + ds_sched_ctrl_op (DSC_BADF, 0, CLR_BUSY); /* sched, clr busy */ + return; + } switch (op) { /* Drive commands */ -case DSC_COLD: /* cold load read */ - ds_fmask = DSC_SPEN; /* sparing enabled */ - ds_cyl = 0; /* cylinder 0 */ - ds_hs = (DSC_GETCHD (ds_cmd) << DSHS_V_HD) | /* reformat hd/sec */ - (DSC_GETCSC (ds_cmd) << DSHS_V_SC); -case DSC_RECAL: /* recalibrate */ -case DSC_SEEK: /* seek */ -case DSC_READ: /* read */ -case DSC_RFULL: /* read full */ -case DSC_ROFF: /* read offset */ -case DSC_RNOVFY: /* read no verify */ -case DSC_VFY: /* verify */ -case DSC_WRITE: /* write */ -case DSC_WFULL: /* write full */ -case DSC_INIT: /* init */ - ds_sr1 = unum; /* init status */ - if (unum >= DS_NUMDR) { /* invalid unit? */ - ds_sched_ctrl_op (DSC_BADU, unum, CLR_BUSY);/* sched, not busy */ - return; - } - if (op == DSC_INIT) ds_sr1 |= /* init? */ - ((cmd & DSC_SPAR)? DS1_SPAR: 0) | /* copy SPD to stat1 */ - ((cmd & DSC_PROT)? DS1_PROT: 0) | - ((cmd & DSC_DFCT)? DS1_DFCT: 0); - ds_unit[unum].FNC = op; /* save op */ - ds_unit[unum].STA &= ~DS2_ATN; /* clear ATN */ - sim_cancel (&ds_unit[unum]); /* cancel current */ - sim_activate (&ds_unit[unum], ds_ctime); /* schedule unit */ - ds_busy = 1; /* set visible busy */ - break; + case DSC_COLD: /* cold load read */ + ds_fmask = DSC_SPEN; /* sparing enabled */ + ds_cyl = 0; /* cylinder 0 */ + ds_hs = (DSC_GETCHD (ds_cmd) << DSHS_V_HD) | /* reformat hd/sec */ + (DSC_GETCSC (ds_cmd) << DSHS_V_SC); + case DSC_RECAL: /* recalibrate */ + case DSC_SEEK: /* seek */ + case DSC_READ: /* read */ + case DSC_RFULL: /* read full */ + case DSC_ROFF: /* read offset */ + case DSC_RNOVFY: /* read no verify */ + case DSC_VFY: /* verify */ + case DSC_WRITE: /* write */ + case DSC_WFULL: /* write full */ + case DSC_INIT: /* init */ + ds_sr1 = unum; /* init status */ + if (unum >= DS_NUMDR) { /* invalid unit? */ + ds_sched_ctrl_op (DSC_BADU, unum, CLR_BUSY);/* sched, not busy */ + return; + } + if (op == DSC_INIT) ds_sr1 |= /* init? */ + ((cmd & DSC_SPAR)? DS1_SPAR: 0) | /* copy SPD to stat1 */ + ((cmd & DSC_PROT)? DS1_PROT: 0) | + ((cmd & DSC_DFCT)? DS1_DFCT: 0); + ds_unit[unum].FNC = op; /* save op */ + ds_unit[unum].STA &= ~DS2_ATN; /* clear ATN */ + sim_cancel (&ds_unit[unum]); /* cancel current */ + sim_activate (&ds_unit[unum], ds_ctime); /* schedule unit */ + ds_busy = 1; /* set visible busy */ + break; /* Read status commands */ -case DSC_RSTA: /* read status */ - dsxb[1] = ds_sr1; /* return SR1 */ - if (unum < DS_NUMDR) { /* and SR2 */ - dsxb[0] = ds_updds2 (&ds_unit[unum]); - ds_unit[unum].STA &= ~DS2_FS; /* clear 1st */ - } - else dsxb[0] = DS2_ERR|DS2_NR; - ds_sched_ctrl_op (DSC_RSTA, 2, SET_BUSY); /* sched 2 wds, busy */ - break; -case DSC_RSA: /* read sector address */ - dtyp = GET_DTYPE (ds_unit[unum].flags); /* get unit type */ - dsxb[0] = GET_CURSEC (ds_dtime * DS_NUMWD, dtyp); /* rot position */ - ds_sched_ctrl_op (DSC_RSTA, 1, SET_BUSY); /* sched 1 wd, busy */ - break; -case DSC_RDA: /* read disk address */ - ds_reqad (&dsxb[1], &dsxb[0]); /* return disk address */ - ds_sched_ctrl_op (DSC_RSTA, 2, SET_BUSY); /* sched 2 wds, busy */ - break; -case DSC_RSYN: /* read syndrome */ - dsxb[6] = ds_sr1; /* return SR1 */ - ds_reqad (&dsxb[5], &dsxb[4]); /* return disk address */ - dsxb[3] = dsxb[2] = dsxb[1] = dsxb[0] = 0; /* syndrome is 0 */ - ds_sched_ctrl_op (DSC_RSTA, 7, SET_BUSY); /* sched 7 wds, busy */ - break; + case DSC_RSTA: /* read status */ + dsxb[1] = ds_sr1; /* return SR1 */ + if (unum < DS_NUMDR) { /* and SR2 */ + dsxb[0] = ds_updds2 (&ds_unit[unum]); + ds_unit[unum].STA &= ~DS2_FS; /* clear 1st */ + } + else dsxb[0] = DS2_ERR|DS2_NR; + ds_sched_ctrl_op (DSC_RSTA, 2, SET_BUSY); /* sched 2 wds, busy */ + break; + + case DSC_RSA: /* read sector address */ + dtyp = GET_DTYPE (ds_unit[unum].flags); /* get unit type */ + dsxb[0] = GET_CURSEC (ds_dtime * DS_NUMWD, dtyp); /* rot position */ + ds_sched_ctrl_op (DSC_RSTA, 1, SET_BUSY); /* sched 1 wd, busy */ + break; + + case DSC_RDA: /* read disk address */ + ds_reqad (&dsxb[1], &dsxb[0]); /* return disk address */ + ds_sched_ctrl_op (DSC_RSTA, 2, SET_BUSY); /* sched 2 wds, busy */ + break; + + case DSC_RSYN: /* read syndrome */ + dsxb[6] = ds_sr1; /* return SR1 */ + ds_reqad (&dsxb[5], &dsxb[4]); /* return disk address */ + dsxb[3] = dsxb[2] = dsxb[1] = dsxb[0] = 0; /* syndrome is 0 */ + ds_sched_ctrl_op (DSC_RSTA, 7, SET_BUSY); /* sched 7 wds, busy */ + break; /* Other controller commands */ -case DSC_SFM: /* set file mask */ -case DSC_CLEAR: /* clear */ -case DSC_AREC: /* address record */ -case DSC_WAKE: /* wakeup */ -case DSC_WTIO: /* write TIO */ - ds_sched_ctrl_op (op, 0, SET_BUSY); /* schedule, busy */ - break; + case DSC_SFM: /* set file mask */ + case DSC_CLEAR: /* clear */ + case DSC_AREC: /* address record */ + case DSC_WAKE: /* wakeup */ + case DSC_WTIO: /* write TIO */ + ds_sched_ctrl_op (op, 0, SET_BUSY); /* schedule, busy */ + break; + + case DSC_END: /* end */ + ds_set_idle (); /* idle ctrl */ + break; + } -case DSC_END: /* end */ - ds_set_idle (); /* idle ctrl */ - break; - } return; } @@ -735,20 +756,20 @@ void ds_doatn (void) { uint32 i, dev; -dev = ds_dib.devno; /* device num */ -for (i = 0; i < DS_NUMDR; i++) { /* intr disabled? */ - ds_lastatn = (ds_lastatn + 1) & DS_DRMASK; /* loop through units */ - if (ds_unit[ds_lastatn].STA & DS2_ATN) { /* ATN set? */ - ds_unit[ds_lastatn].STA &= ~DS2_ATN; /* clear ATN */ - setFLG (dev); /* request interrupt */ - ds_sr1 = DS1_ATN | ds_lastatn; /* set up status 1 */ - ds_state = DS_WAIT; /* block atn intrs */ - return; - } - } +dev = ds_dib.devno; /* device num */ +for (i = 0; i < DS_NUMDR; i++) { /* intr disabled? */ + ds_lastatn = (ds_lastatn + 1) & DS_DRMASK; /* loop through units */ + if (ds_unit[ds_lastatn].STA & DS2_ATN) { /* ATN set? */ + ds_unit[ds_lastatn].STA &= ~DS2_ATN; /* clear ATN */ + setFLG (dev); /* request interrupt */ + ds_sr1 = DS1_ATN | ds_lastatn; /* set up status 1 */ + ds_state = DS_WAIT; /* block atn intrs */ + return; + } + } return; } - + /* Controller service The argument for the function, if any, is stored in uptr->CYL */ @@ -761,71 +782,72 @@ op = uptr->FNC; dev = ds_dib.devno; switch (op) { -case DSC_AREC: /* address record */ - ds_wait_for_cpu (uptr, DSC_AREC|DSC_2ND); /* set flag, new state */ - break; -case DSC_AREC | DSC_2ND: /* poll done */ - if (!DS_FIFO_EMPTY) { /* OTA ds? */ - ds_cyl = ds_fifo_read (); /* save cylinder */ - ds_wait_for_cpu (uptr, DSC_AREC|DSC_3RD); /* set flag, new state */ - } - else sim_activate (uptr, ds_ctime); /* no, continue poll */ - break; -case DSC_AREC | DSC_3RD: /* poll done */ - if (!DS_FIFO_EMPTY) { /* OTA ds? */ - ds_hs = ds_fifo_read (); /* save head/sector */ - ds_cmd_done (0, DS1_OK); /* op done, no flag */ - } - else sim_activate (uptr, ds_ctime); /* no, continue poll */ - break; + case DSC_AREC: /* address record */ + ds_wait_for_cpu (uptr, DSC_AREC|DSC_2ND); /* set flag, new state */ + break; + case DSC_AREC | DSC_2ND: /* poll done */ + if (!DS_FIFO_EMPTY) { /* OTA ds? */ + ds_cyl = ds_fifo_read (); /* save cylinder */ + ds_wait_for_cpu (uptr, DSC_AREC|DSC_3RD); /* set flag, new state */ + } + else sim_activate (uptr, ds_ctime); /* no, continue poll */ + break; + case DSC_AREC | DSC_3RD: /* poll done */ + if (!DS_FIFO_EMPTY) { /* OTA ds? */ + ds_hs = ds_fifo_read (); /* save head/sector */ + ds_cmd_done (0, DS1_OK); /* op done, no flag */ + } + else sim_activate (uptr, ds_ctime); /* no, continue poll */ + break; -case DSC_RSTA: /* rd stat (all forms) */ - if (DS_FIFO_EMPTY) { /* fifo empty? */ - uptr->CYL--; - ds_fifo_write (dsxb[uptr->CYL]); /* store next status */ - ds_wait_for_cpu (uptr, DSC_RSTA | - (uptr->CYL? 0: DSC_2ND)); /* set flag, new state */ - } - else sim_activate (uptr, ds_ctime); /* no, continue poll */ - break; -case DSC_RSTA | DSC_2ND: /* poll done */ - if (DS_FIFO_EMPTY) ds_cmd_done (0, DS1_OK); /* op done? no flag */ - else sim_activate (uptr, ds_ctime); /* no, continue poll */ - break; + case DSC_RSTA: /* rd stat (all forms) */ + if (DS_FIFO_EMPTY) { /* fifo empty? */ + uptr->CYL--; + ds_fifo_write (dsxb[uptr->CYL]); /* store next status */ + ds_wait_for_cpu (uptr, DSC_RSTA | + (uptr->CYL? 0: DSC_2ND)); /* set flag, new state */ + } + else sim_activate (uptr, ds_ctime); /* no, continue poll */ + break; + case DSC_RSTA | DSC_2ND: /* poll done */ + if (DS_FIFO_EMPTY) ds_cmd_done (0, DS1_OK); /* op done? no flag */ + else sim_activate (uptr, ds_ctime); /* no, continue poll */ + break; -case DSC_CLEAR: /* clear */ - ds_reset_cmn (&ds_dev); /* reset ctrl */ - clrCTL (dev); /* clear CTL, SRQ */ - clrSRQ (dev); - ds_cmd_done (1, DS1_OK); /* op done, set flag */ - break; + case DSC_CLEAR: /* clear */ + ds_reset_cmn (&ds_dev); /* reset ctrl */ + clrCTL (dev); /* clear CTL, SRQ */ + clrSRQ (dev); + ds_cmd_done (1, DS1_OK); /* op done, set flag */ + break; -case DSC_SFM: /* set file mask */ - ds_fmask = ds_cmd & DSC_FMASK; - ds_cmd_done (1, DS1_OK); /* op done, set flag */ - break; + case DSC_SFM: /* set file mask */ + ds_fmask = ds_cmd & DSC_FMASK; + ds_cmd_done (1, DS1_OK); /* op done, set flag */ + break; -case DSC_WTIO: /* write I/O */ - ds_cmd_done (0, DS1_OK); /* op done, no flag */ - break; + case DSC_WTIO: /* write I/O */ + ds_cmd_done (0, DS1_OK); /* op done, no flag */ + break; -case DSC_WAKE: /* wakeup */ - ds_cmd_done (1, DS1_AVAIL); /* op done, set flag */ - break; + case DSC_WAKE: /* wakeup */ + ds_cmd_done (1, DS1_AVAIL); /* op done, set flag */ + break; -case DSC_BADU: /* invalid unit */ - if (uptr->CYL > 10) ds_cmd_done (1, DS1_UNAVL); /* [11,16]? bad unit */ - else ds_cmd_done (1, DS1_S2ERR); /* else unit not ready */ - break; + case DSC_BADU: /* invalid unit */ + if (uptr->CYL > 10) ds_cmd_done (1, DS1_UNAVL); /* [11,16]? bad unit */ + else ds_cmd_done (1, DS1_S2ERR); /* else unit not ready */ + break; -case DSC_BADF: /* invalid operation */ - ds_cmd_done (1, DS1_ILLOP); /* op done, set flag */ - break; + case DSC_BADF: /* invalid operation */ + ds_cmd_done (1, DS1_ILLOP); /* op done, set flag */ + break; -default: - return SCPE_IERR; - } -ds_poll (); /* run the controller */ + default: + return SCPE_IERR; + } + +ds_poll (); /* run the controller */ return SCPE_OK; } @@ -835,14 +857,14 @@ t_stat ds_svc_t (UNIT *uptr) { int32 i; -for (i = 0; i < (DS_NUMDR + 1); i++) /* cancel all ops */ - sim_cancel (&ds_unit[i]); -ds_set_idle (); /* idle the controller */ -ds_fmask = 0; /* clear file mask */ -ds_poll (); /* run the controller */ +for (i = 0; i < (DS_NUMDR + 1); i++) /* cancel all ops */ + sim_cancel (&ds_unit[i]); +ds_set_idle (); /* idle the controller */ +ds_fmask = 0; /* clear file mask */ +ds_poll (); /* run the controller */ return SCPE_OK; } - + /* Unit service */ t_stat ds_svc_u (UNIT *uptr) @@ -853,163 +875,165 @@ t_stat r; op = uptr->FNC; dev = ds_dib.devno; dtyp = GET_DTYPE (uptr->flags); -switch (op) { /* case on function */ +switch (op) { /* case on function */ /* Seek and recalibrate */ -case DSC_RECAL: /* recalibrate */ - if ((uptr->flags & UNIT_UNLOAD) == 0) { /* drive up? */ - ds_start_seek (uptr, 0, DSC_RECAL|DSC_2ND); /* set up seek */ - ds_set_idle (); /* ctrl is idle */ - } - else ds_cmd_done (1, DS1_S2ERR); /* not ready error */ - break; -case DSC_RECAL | DSC_2ND: /* recal complete */ - uptr->STA = uptr->STA | DS2_ATN; /* set attention */ - break; + case DSC_RECAL: /* recalibrate */ + if ((uptr->flags & UNIT_UNLOAD) == 0) { /* drive up? */ + ds_start_seek (uptr, 0, DSC_RECAL|DSC_2ND); /* set up seek */ + ds_set_idle (); /* ctrl is idle */ + } + else ds_cmd_done (1, DS1_S2ERR); /* not ready error */ + break; + case DSC_RECAL | DSC_2ND: /* recal complete */ + uptr->STA = uptr->STA | DS2_ATN; /* set attention */ + break; + + case DSC_SEEK: /* seek */ + ds_wait_for_cpu (uptr, DSC_SEEK|DSC_2ND); /* set flag, new state */ + break; + case DSC_SEEK | DSC_2ND: /* waiting for word 1 */ + if (!DS_FIFO_EMPTY) { /* OTA ds? */ + ds_cyl = ds_fifo_read (); /* save cylinder */ + ds_wait_for_cpu (uptr, DSC_SEEK|DSC_3RD); /* set flag, new state */ + } + else sim_activate (uptr, ds_ctime); /* no, continue poll */ + break; + case DSC_SEEK | DSC_3RD: /* waiting for word 2 */ + if (!DS_FIFO_EMPTY) { /* OTA ds? */ + ds_hs = ds_fifo_read (); /* save head/sector */ + if ((uptr->flags & UNIT_UNLOAD) == 0) { /* drive up? */ + ds_start_seek (uptr, ds_cyl, DSC_SEEK|DSC_4TH); /* set up seek */ + ds_set_idle (); /* ctrl is idle */ + } + else ds_cmd_done (1, DS1_S2ERR); /* else not ready error */ + } + else sim_activate (uptr, ds_ctime); /* continue poll */ + break; + case DSC_SEEK | DSC_4TH: /* seek complete */ + uptr->STA = uptr->STA | DS2_ATN; /* set attention */ + break; -case DSC_SEEK: /* seek */ - ds_wait_for_cpu (uptr, DSC_SEEK|DSC_2ND); /* set flag, new state */ - break; -case DSC_SEEK | DSC_2ND: /* waiting for word 1 */ - if (!DS_FIFO_EMPTY) { /* OTA ds? */ - ds_cyl = ds_fifo_read (); /* save cylinder */ - ds_wait_for_cpu (uptr, DSC_SEEK|DSC_3RD); /* set flag, new state */ - } - else sim_activate (uptr, ds_ctime); /* no, continue poll */ - break; -case DSC_SEEK | DSC_3RD: /* waiting for word 2 */ - if (!DS_FIFO_EMPTY) { /* OTA ds? */ - ds_hs = ds_fifo_read (); /* save head/sector */ - if ((uptr->flags & UNIT_UNLOAD) == 0) { /* drive up? */ - ds_start_seek (uptr, ds_cyl, DSC_SEEK|DSC_4TH); /* set up seek */ - ds_set_idle (); /* ctrl is idle */ - } - else ds_cmd_done (1, DS1_S2ERR); /* else not ready error */ - } - else sim_activate (uptr, ds_ctime); /* continue poll */ - break; -case DSC_SEEK | DSC_4TH: /* seek complete */ - uptr->STA = uptr->STA | DS2_ATN; /* set attention */ - break; - /* Read variants */ -case DSC_ROFF: /* read with offset */ - ds_wait_for_cpu (uptr, DSC_ROFF|DSC_2ND); /* set flag, new state */ - break; -case DSC_ROFF | DSC_2ND: /* poll done */ - if (!DS_FIFO_EMPTY) { /* OTA ds? new state */ - ds_fifo_read (); /* drain fifo */ - uptr->FNC = DSC_READ; - setFLG (dev); /* handshake */ - } - sim_activate (uptr, ds_ctime); /* schedule unit */ - break; + case DSC_ROFF: /* read with offset */ + ds_wait_for_cpu (uptr, DSC_ROFF|DSC_2ND); /* set flag, new state */ + break; + case DSC_ROFF | DSC_2ND: /* poll done */ + if (!DS_FIFO_EMPTY) { /* OTA ds? new state */ + ds_fifo_read (); /* drain fifo */ + uptr->FNC = DSC_READ; + setFLG (dev); /* handshake */ + } + sim_activate (uptr, ds_ctime); /* schedule unit */ + break; -case DSC_COLD: /* cold load read */ - if ((uptr->flags & UNIT_UNLOAD) == 0) /* drive up? */ - ds_start_seek (uptr, 0, DSC_READ); /* set up seek */ - else ds_cmd_done (1, DS1_S2ERR); /* no, not ready error */ - break; + case DSC_COLD: /* cold load read */ + if ((uptr->flags & UNIT_UNLOAD) == 0) /* drive up? */ + ds_start_seek (uptr, 0, DSC_READ); /* set up seek */ + else ds_cmd_done (1, DS1_S2ERR); /* no, not ready error */ + break; -case DSC_READ: /* read */ - if (r = ds_start_rd (uptr, 0, 1)) return r; /* new sector; error? */ - break; -case DSC_READ | DSC_2ND: /* word transfer */ - ds_cont_rd (uptr, DS_NUMWD); /* xfr wd, check end */ - break; -case DSC_READ | DSC_3RD: /* end of sector */ - ds_end_rw (uptr, DSC_READ); /* see if more to do */ - break; + case DSC_READ: /* read */ + if (r = ds_start_rd (uptr, 0, 1)) return r; /* new sector; error? */ + break; + case DSC_READ | DSC_2ND: /* word transfer */ + ds_cont_rd (uptr, DS_NUMWD); /* xfr wd, check end */ + break; + case DSC_READ | DSC_3RD: /* end of sector */ + ds_end_rw (uptr, DSC_READ); /* see if more to do */ + break; -case DSC_RNOVFY: /* read, no verify */ - if (r = ds_start_rd (uptr, 0, 0)) return r; /* new sector; error? */ - break; -case DSC_RNOVFY | DSC_2ND: /* word transfer */ - ds_cont_rd (uptr, DS_NUMWD); /* xfr wd, check end */ - break; -case DSC_RNOVFY | DSC_3RD: /* end of sector */ - ds_end_rw (uptr, DSC_RNOVFY); /* see if more to do */ - break; + case DSC_RNOVFY: /* read, no verify */ + if (r = ds_start_rd (uptr, 0, 0)) return r; /* new sector; error? */ + break; + case DSC_RNOVFY | DSC_2ND: /* word transfer */ + ds_cont_rd (uptr, DS_NUMWD); /* xfr wd, check end */ + break; + case DSC_RNOVFY | DSC_3RD: /* end of sector */ + ds_end_rw (uptr, DSC_RNOVFY); /* see if more to do */ + break; -case DSC_RFULL: /* read full */ - dsxb[DS_FSYNC] = 0100376; /* fill in header */ - dsxb[DS_FCYL] = uptr->CYL; - dsxb[DS_FHS] = ds_hs; /* before h/s update */ - if (r = ds_start_rd (uptr, DS_FDATA, 0)) /* new sector; error? */ - return r; - break; -case DSC_RFULL | DSC_2ND: /* word transfer */ - ds_cont_rd (uptr, DS_NUMWDF); /* xfr wd, check end */ - break; -case DSC_RFULL | DSC_3RD: /* end of sector */ - ds_end_rw (uptr, DSC_RFULL); /* see if more to do */ - break; + case DSC_RFULL: /* read full */ + dsxb[DS_FSYNC] = 0100376; /* fill in header */ + dsxb[DS_FCYL] = uptr->CYL; + dsxb[DS_FHS] = ds_hs; /* before h/s update */ + if (r = ds_start_rd (uptr, DS_FDATA, 0)) /* new sector; error? */ + return r; + break; + case DSC_RFULL | DSC_2ND: /* word transfer */ + ds_cont_rd (uptr, DS_NUMWDF); /* xfr wd, check end */ + break; + case DSC_RFULL | DSC_3RD: /* end of sector */ + ds_end_rw (uptr, DSC_RFULL); /* see if more to do */ + break; + + case DSC_VFY: /* verify */ + ds_wait_for_cpu (uptr, DSC_VFY|DSC_2ND); /* set flag, new state */ + break; + case DSC_VFY | DSC_2ND: /* poll done */ + if (!DS_FIFO_EMPTY) { /* OTA ds? */ + ds_vctr = ds_fifo_read (); /* save count */ + uptr->FNC = DSC_VFY | DSC_3RD; /* next state */ + sim_activate (uptr, ds_rtime); /* delay for transfer */ + } + else sim_activate (uptr, ds_ctime); /* no, continue poll */ + break; + case DSC_VFY | DSC_3RD: /* start sector */ + if (ds_start_rw (uptr, ds_dtime * DS_NUMWD, 1)) break; + /* new sector; error? */ + ds_next_sec (uptr); /* increment hd, sc */ + break; + case DSC_VFY | DSC_4TH: /* end sector */ + ds_vctr = (ds_vctr - 1) & DMASK; /* decrement count */ + if (ds_vctr) ds_end_rw (uptr, DSC_VFY|DSC_3RD); /* more to do? */ + else ds_cmd_done (1, DS1_OK); /* no, set done */ + break; -case DSC_VFY: /* verify */ - ds_wait_for_cpu (uptr, DSC_VFY|DSC_2ND); /* set flag, new state */ - break; -case DSC_VFY | DSC_2ND: /* poll done */ - if (!DS_FIFO_EMPTY) { /* OTA ds? */ - ds_vctr = ds_fifo_read (); /* save count */ - uptr->FNC = DSC_VFY | DSC_3RD; /* next state */ - sim_activate (uptr, ds_rtime); /* delay for transfer */ - } - else sim_activate (uptr, ds_ctime); /* no, continue poll */ - break; -case DSC_VFY | DSC_3RD: /* start sector */ - if (ds_start_rw (uptr, ds_dtime * DS_NUMWD, 1)) break; - /* new sector; error? */ - ds_next_sec (uptr); /* increment hd, sc */ - break; -case DSC_VFY | DSC_4TH: /* end sector */ - ds_vctr = (ds_vctr - 1) & DMASK; /* decrement count */ - if (ds_vctr) ds_end_rw (uptr, DSC_VFY|DSC_3RD); /* more to do? */ - else ds_cmd_done (1, DS1_OK); /* no, set done */ - break; - /* Write variants */ -case DSC_WRITE: /* write */ - ds_start_wr (uptr, 1); /* new sector */ - break; -case DSC_WRITE | DSC_2ND: - if (r = ds_cont_wr (uptr, 0, DS_NUMWD)) /* write word */ - return r; /* error? */ - break; -case DSC_WRITE | DSC_3RD: /* end sector */ - ds_end_rw (uptr, DSC_WRITE); /* see if more to do */ - break; + case DSC_WRITE: /* write */ + ds_start_wr (uptr, 1); /* new sector */ + break; + case DSC_WRITE | DSC_2ND: + if (r = ds_cont_wr (uptr, 0, DS_NUMWD)) /* write word */ + return r; /* error? */ + break; + case DSC_WRITE | DSC_3RD: /* end sector */ + ds_end_rw (uptr, DSC_WRITE); /* see if more to do */ + break; -case DSC_INIT: /* init */ - ds_start_wr (uptr, 0); /* new sector */ - break; -case DSC_INIT | DSC_2ND: - if (r = ds_cont_wr (uptr, 0, DS_NUMWD)) /* write word */ - return r; /* error? */ - break; -case DSC_INIT | DSC_3RD: /* end sector */ - ds_end_rw (uptr, DSC_INIT); /* see if more to do */ - break; + case DSC_INIT: /* init */ + ds_start_wr (uptr, 0); /* new sector */ + break; + case DSC_INIT | DSC_2ND: + if (r = ds_cont_wr (uptr, 0, DS_NUMWD)) /* write word */ + return r; /* error? */ + break; + case DSC_INIT | DSC_3RD: /* end sector */ + ds_end_rw (uptr, DSC_INIT); /* see if more to do */ + break; -case DSC_WFULL: /* write full */ - ds_start_wr (uptr, 0); /* new sector */ - break; -case DSC_WFULL | DSC_2ND: - if (r = ds_cont_wr (uptr, DS_FDATA, DS_NUMWDF)) /* write word */ - return r; /* error */ - break; -case DSC_WFULL | DSC_3RD: - ds_end_rw (uptr, DSC_WFULL); /* see if more to do */ - break; + case DSC_WFULL: /* write full */ + ds_start_wr (uptr, 0); /* new sector */ + break; + case DSC_WFULL | DSC_2ND: + if (r = ds_cont_wr (uptr, DS_FDATA, DS_NUMWDF)) /* write word */ + return r; /* error */ + break; + case DSC_WFULL | DSC_3RD: + ds_end_rw (uptr, DSC_WFULL); /* see if more to do */ + break; + + default: + break; + } -default: - break; } ds_poll (); return SCPE_OK; -} - +} + /* Schedule timed wait for CPU response - Set flag to get CPU attention @@ -1020,10 +1044,10 @@ void ds_wait_for_cpu (UNIT *uptr, uint32 newst) { uint32 dev = ds_dib.devno; -setFLG (dev); /* set flag */ -uptr->FNC = newst; /* new state */ -sim_activate (uptr, ds_ctime); /* activate unit */ -sim_cancel (&ds_timer); /* activate timeout */ +setFLG (dev); /* set flag */ +uptr->FNC = newst; /* new state */ +sim_activate (uptr, ds_ctime); /* activate unit */ +sim_cancel (&ds_timer); /* activate timeout */ sim_activate (&ds_timer, ds_tmo); return; } @@ -1036,9 +1060,9 @@ return; void ds_set_idle (void) { -ds_busy = 0; /* busy clear */ -ds_state = DS_IDLE; /* ctrl idle */ -sim_cancel (&ds_timer); /* no timeout */ +ds_busy = 0; /* busy clear */ +ds_state = DS_IDLE; /* ctrl idle */ +sim_cancel (&ds_timer); /* no timeout */ return; } @@ -1053,11 +1077,11 @@ void ds_cmd_done (t_bool sf, uint32 sr1) { uint32 dev = ds_dib.devno; -if (sf) { setFLG (dev); } /* set host flag */ -ds_busy = 0; /* clear visible busy */ -ds_sr1 = ds_sr1 | sr1; /* final status */ -ds_state = DS_WAIT; /* ctrl waiting */ -sim_cancel (&ds_timer); /* activate timeout */ +if (sf) { setFLG (dev); } /* set host flag */ +ds_busy = 0; /* clear visible busy */ +ds_sr1 = ds_sr1 | sr1; /* final status */ +ds_state = DS_WAIT; /* ctrl waiting */ +sim_cancel (&ds_timer); /* activate timeout */ sim_activate (&ds_timer, ds_tmo); return; } @@ -1069,13 +1093,13 @@ uint32 ds_updds2 (UNIT *uptr) uint32 sta; uint32 dtyp = GET_DTYPE (uptr->flags); -sta = drv_tab[dtyp].id | /* form status */ - uptr->STA | /* static bits */ - ((uptr->flags & UNIT_WPR)? DS2_RO: 0) | /* dynamic bits */ - ((uptr->flags & UNIT_FMT)? DS2_FRM: 0) | - ((uptr->flags & UNIT_UNLOAD)? DS2_NR | DS2_BS: 0) | - (sim_is_active (uptr)? DS2_BS: 0); -if (sta & DS2_ALLERR) sta = sta | DS2_ERR; /* set error */ +sta = drv_tab[dtyp].id | /* form status */ + uptr->STA | /* static bits */ + ((uptr->flags & UNIT_WPR)? DS2_RO: 0) | /* dynamic bits */ + ((uptr->flags & UNIT_FMT)? DS2_FRM: 0) | + ((uptr->flags & UNIT_UNLOAD)? DS2_NR | DS2_BS: 0) | + (sim_is_active (uptr)? DS2_BS: 0); +if (sta & DS2_ALLERR) sta = sta | DS2_ERR; /* set error */ return sta; } @@ -1083,11 +1107,11 @@ return sta; void ds_sched_ctrl_op (uint32 op, uint32 arg, uint32 busy) { -ds_ctrl.FNC = op; /* save op */ -ds_ctrl.CYL = arg; /* save argument */ -ds_busy = busy; /* set visible busy */ -sim_activate (&ds_ctrl, ds_ctime); /* schedule */ -sim_cancel (&ds_timer); /* activate timeout */ +ds_ctrl.FNC = op; /* save op */ +ds_ctrl.CYL = arg; /* save argument */ +ds_busy = busy; /* set visible busy */ +sim_activate (&ds_ctrl, ds_ctime); /* schedule */ +sim_cancel (&ds_timer); /* activate timeout */ sim_activate (&ds_timer, ds_tmo); return; } @@ -1109,21 +1133,22 @@ int32 t; uint32 hd, sc; uint32 dtyp = GET_DTYPE (uptr->flags); -uptr->FNC = newst; /* set new state */ -if (cyl >= drv_tab[dtyp].cyl) { /* out of bounds? */ - t = 0; /* don't change cyl */ - uptr->STA = uptr->STA | DS2_SC; /* set seek check */ - } -else { t = abs (uptr->CYL - cyl); /* delta cylinders */ - uptr->CYL = cyl; /* put on cylinder */ - hd = DSHS_GETHD (ds_hs); /* invalid head or sec? */ - sc = DSHS_GETSC (ds_hs); - if ((hd >= drv_tab[dtyp].hd) || - (sc >= drv_tab[dtyp].sc)) - uptr->STA = uptr->STA | DS2_SC; /* set seek check */ - else uptr->STA = uptr->STA & ~DS2_SC; /* clear seek check */ - } -sim_activate (uptr, ds_stime * (t + 1)); /* schedule */ +uptr->FNC = newst; /* set new state */ +if (cyl >= drv_tab[dtyp].cyl) { /* out of bounds? */ + t = 0; /* don't change cyl */ + uptr->STA = uptr->STA | DS2_SC; /* set seek check */ + } +else { + t = abs (uptr->CYL - cyl); /* delta cylinders */ + uptr->CYL = cyl; /* put on cylinder */ + hd = DSHS_GETHD (ds_hs); /* invalid head or sec? */ + sc = DSHS_GETSC (ds_hs); + if ((hd >= drv_tab[dtyp].hd) || + (sc >= drv_tab[dtyp].sc)) + uptr->STA = uptr->STA | DS2_SC; /* set seek check */ + else uptr->STA = uptr->STA & ~DS2_SC; /* clear seek check */ + } +sim_activate (uptr, ds_stime * (t + 1)); /* schedule */ return; } @@ -1139,38 +1164,38 @@ t_bool ds_start_rw (UNIT *uptr, int32 tm, t_bool vfy) uint32 da, hd, sc; uint32 dtyp = GET_DTYPE (uptr->flags); -ds_eod = 0; /* init eod */ -ds_ptr = 0; /* init buffer ptr */ -if (uptr->flags & UNIT_UNLOAD) { /* drive down? */ - ds_cmd_done (1, DS1_S2ERR); - return TRUE; - } -if (ds_eoc) { /* at end of cylinder? */ - ds_next_cyl (uptr); /* auto seek to next */ - return TRUE; /* or error */ - } -if (vfy && ((uint32) uptr->CYL != ds_cyl)) { /* on wrong cylinder? */ - if (ds_cyl >= drv_tab[dtyp].cyl) /* seeking to bad? */ - ds_cmd_done (1, DS1_CYLCE); /* lose */ - else ds_start_seek (uptr, ds_cyl, uptr->FNC); /* seek right cyl */ - return TRUE; - } +ds_eod = 0; /* init eod */ +ds_ptr = 0; /* init buffer ptr */ +if (uptr->flags & UNIT_UNLOAD) { /* drive down? */ + ds_cmd_done (1, DS1_S2ERR); + return TRUE; + } +if (ds_eoc) { /* at end of cylinder? */ + ds_next_cyl (uptr); /* auto seek to next */ + return TRUE; /* or error */ + } +if (vfy && ((uint32) uptr->CYL != ds_cyl)) { /* on wrong cylinder? */ + if (ds_cyl >= drv_tab[dtyp].cyl) /* seeking to bad? */ + ds_cmd_done (1, DS1_CYLCE); /* lose */ + else ds_start_seek (uptr, ds_cyl, uptr->FNC); /* seek right cyl */ + return TRUE; + } hd = DSHS_GETHD (ds_hs); sc = DSHS_GETSC (ds_hs); -if ((uint32) uptr->CYL >= drv_tab[dtyp].cyl) { /* valid cylinder? */ - uptr->STA = uptr->STA | DS2_SC; /* set seek check */ - ds_cmd_done (1, DS1_S2ERR); /* error */ - return TRUE; - } -if ((hd >= drv_tab[dtyp].hd) || /* valid head, sector? */ - (sc >= drv_tab[dtyp].sc)) { - ds_cmd_done (1, DS1_HSCE); /* no, error */ - return TRUE; - } -da = GET_DA (uptr->CYL, hd, sc, dtyp); /* position in file */ +if ((uint32) uptr->CYL >= drv_tab[dtyp].cyl) { /* valid cylinder? */ + uptr->STA = uptr->STA | DS2_SC; /* set seek check */ + ds_cmd_done (1, DS1_S2ERR); /* error */ + return TRUE; + } +if ((hd >= drv_tab[dtyp].hd) || /* valid head, sector? */ + (sc >= drv_tab[dtyp].sc)) { + ds_cmd_done (1, DS1_HSCE); /* no, error */ + return TRUE; + } +da = GET_DA (uptr->CYL, hd, sc, dtyp); /* position in file */ sim_fseek (uptr->fileref, da * sizeof (uint16), SEEK_SET); /* set file pos */ -uptr->FNC += DSC_NEXT; /* next state */ -sim_activate (uptr, tm); /* activate unit */ +uptr->FNC += DSC_NEXT; /* next state */ +sim_activate (uptr, tm); /* activate unit */ return FALSE; } @@ -1188,12 +1213,12 @@ t_stat ds_start_rd (UNIT *uptr, uint32 off, t_bool vfy) { uint32 t; -if (ds_start_rw (uptr, ds_rtime, vfy)) return SCPE_OK; /* new sec; err or seek? */ +if (ds_start_rw (uptr, ds_rtime, vfy)) return SCPE_OK; /* new sec; err or seek? */ t = sim_fread (dsxb + off, sizeof (uint16), DS_NUMWD, uptr->fileref); -for (t = t + off ; t < DS_NUMWDF; t++) dsxb[t] = 0; /* fill sector */ -if (ferror (uptr->fileref)) /* error? */ - return ds_set_uncorr (uptr); /* say uncorrectable */ -ds_next_sec (uptr); /* increment hd, sc */ +for (t = t + off ; t < DS_NUMWDF; t++) dsxb[t] = 0; /* fill sector */ +if (ferror (uptr->fileref)) /* error? */ + return ds_set_uncorr (uptr); /* say uncorrectable */ +ds_next_sec (uptr); /* increment hd, sc */ return SCPE_OK; } @@ -1211,14 +1236,14 @@ void ds_start_wr (UNIT *uptr, t_bool vfy) uint32 i; uint32 dev = ds_dib.devno; -if ((uptr->flags & UNIT_WPR) || /* write protected? */ - (!vfy && ((uptr->flags & UNIT_FMT) == 0))) { /* format, not enbl? */ - ds_cmd_done (1, DS1_S2ERR); /* error */ - return; - } -if (ds_start_rw (uptr, ds_rtime, vfy)) return; /* new sec; err or seek? */ -for (i = 0; i < DS_NUMWDF; i++) dsxb[i] = 0; /* clear buffer */ -setSRQ (dev); /* request word */ +if ((uptr->flags & UNIT_WPR) || /* write protected? */ + (!vfy && ((uptr->flags & UNIT_FMT) == 0))) { /* format, not enbl? */ + ds_cmd_done (1, DS1_S2ERR); /* error */ + return; + } +if (ds_start_rw (uptr, ds_rtime, vfy)) return; /* new sec; err or seek? */ +for (i = 0; i < DS_NUMWDF; i++) dsxb[i] = 0; /* clear buffer */ +setSRQ (dev); /* request word */ return; } @@ -1228,15 +1253,15 @@ void ds_next_sec (UNIT *uptr) { uint32 dtyp = GET_DTYPE (uptr->flags); -ds_hs = ds_hs + 1; /* increment sector */ -if (DSHS_GETSC (ds_hs) < drv_tab[dtyp].sc) return; /* end of track? */ -ds_hs = ds_hs & ~DSHS_SC; /* yes, wrap sector */ -if (ds_fmask & DSC_CYLM) { /* cylinder mode? */ - ds_hs = ds_hs + (1 << DSHS_V_HD); /* increment head */ - if (DSHS_GETHD (ds_hs) < drv_tab[dtyp].hd) return; /* end of cyl? */ - ds_hs = ds_hs & ~DSHS_HD; /* 0 head */ - } -ds_eoc = 1; /* flag end cylinder */ +ds_hs = ds_hs + 1; /* increment sector */ +if (DSHS_GETSC (ds_hs) < drv_tab[dtyp].sc) return; /* end of track? */ +ds_hs = ds_hs & ~DSHS_SC; /* yes, wrap sector */ +if (ds_fmask & DSC_CYLM) { /* cylinder mode? */ + ds_hs = ds_hs + (1 << DSHS_V_HD); /* increment head */ + if (DSHS_GETHD (ds_hs) < drv_tab[dtyp].hd) return; /* end of cyl? */ + ds_hs = ds_hs & ~DSHS_HD; /* 0 head */ + } +ds_eoc = 1; /* flag end cylinder */ return; } @@ -1247,13 +1272,13 @@ return; void ds_next_cyl (UNIT *uptr) { -if (ds_fmask & DSC_AUTO) { /* auto seek allowed? */ - if (ds_fmask & DSC_DECR) ds_cyl = (ds_cyl - 1) & DMASK; - else ds_cyl = (ds_cyl + 1) & DMASK; - ds_eoc = 0; /* clear end cylinder */ - ds_start_seek (uptr, ds_cyl, uptr->FNC); /* seek, same state */ - } -else ds_cmd_done (1, DS1_EOCYL); /* no, end of cyl err */ +if (ds_fmask & DSC_AUTO) { /* auto seek allowed? */ + if (ds_fmask & DSC_DECR) ds_cyl = (ds_cyl - 1) & DMASK; + else ds_cyl = (ds_cyl + 1) & DMASK; + ds_eoc = 0; /* clear end cylinder */ + ds_start_seek (uptr, ds_cyl, uptr->FNC); /* seek, same state */ + } +else ds_cmd_done (1, DS1_EOCYL); /* no, end of cyl err */ return; } @@ -1266,16 +1291,16 @@ void ds_cont_rd (UNIT *uptr, uint32 bsize) { uint32 dev = ds_dib.devno; -if (ds_eod) ds_cmd_done (1, DS1_OK); /* DMA end? done */ -else if (SRQ (dev)) { /* overrun? */ - ds_cmd_done (1, DS1_OVRUN); /* set done */ - return; - } -else { ds_fifo_write (dsxb[ds_ptr++]); /* next word */ - setSRQ (dev); /* request service */ - if (ds_ptr >= bsize) uptr->FNC += DSC_NEXT; /* sec done? next state */ - sim_activate (uptr, ds_dtime); /* schedule */ - } +if (ds_eod) ds_cmd_done (1, DS1_OK); /* DMA end? done */ +else if (SRQ (dev)) { /* overrun? */ + ds_cmd_done (1, DS1_OVRUN); /* set done */ + return; + } +else { ds_fifo_write (dsxb[ds_ptr++]); /* next word */ + setSRQ (dev); /* request service */ + if (ds_ptr >= bsize) uptr->FNC += DSC_NEXT; /* sec done? next state */ + sim_activate (uptr, ds_dtime); /* schedule */ + } return; } @@ -1291,25 +1316,25 @@ t_stat ds_cont_wr (UNIT *uptr, uint32 off, uint32 bsize) uint32 i, dat; uint32 dev = ds_dib.devno; -if (SRQ (dev)) { /* overrun? */ - ds_cmd_done (1, DS1_OVRUN); /* set done */ - return SCPE_OK; - } -dsxb[ds_ptr++] = dat = ds_fifo_read (); /* next word */ -if (ds_eod || (ds_ptr >= bsize)) { /* xfr or sector done? */ - for (i = ds_ptr; i < bsize; i++) dsxb[i] = dat; /* fill sector */ - sim_fwrite (dsxb + off, sizeof (uint16), DS_NUMWD, uptr->fileref); - if (ferror (uptr->fileref)) /* error on write? */ - return ds_set_uncorr (uptr); /* uncorrectable */ - ds_next_sec (uptr); /* increment hd, sc */ - if (ds_eod) { /* end data? */ - ds_cmd_done (1, DS1_OK); /* set done */ - return SCPE_OK; - } - else uptr->FNC += DSC_NEXT; /* no, next state */ - } -else { setSRQ (dev); } /* request next word */ -sim_activate (uptr, ds_dtime); /* schedule */ +if (SRQ (dev)) { /* overrun? */ + ds_cmd_done (1, DS1_OVRUN); /* set done */ + return SCPE_OK; + } +dsxb[ds_ptr++] = dat = ds_fifo_read (); /* next word */ +if (ds_eod || (ds_ptr >= bsize)) { /* xfr or sector done? */ + for (i = ds_ptr; i < bsize; i++) dsxb[i] = dat; /* fill sector */ + sim_fwrite (dsxb + off, sizeof (uint16), DS_NUMWD, uptr->fileref); + if (ferror (uptr->fileref)) /* error on write? */ + return ds_set_uncorr (uptr); /* uncorrectable */ + ds_next_sec (uptr); /* increment hd, sc */ + if (ds_eod) { /* end data? */ + ds_cmd_done (1, DS1_OK); /* set done */ + return SCPE_OK; + } + else uptr->FNC += DSC_NEXT; /* no, next state */ + } +else { setSRQ (dev); } /* request next word */ +sim_activate (uptr, ds_dtime); /* schedule */ return SCPE_OK; } @@ -1321,10 +1346,10 @@ return SCPE_OK; void ds_end_rw (UNIT *uptr, uint32 newst) { -uptr->FNC = newst; /* new state */ -if (ds_eod) ds_cmd_done (1, DS1_OK); /* done? */ -else if (ds_eoc) ds_next_cyl (uptr); /* end cyl? seek */ -else sim_activate (uptr, ds_rtime); /* normal transfer */ +uptr->FNC = newst; /* new state */ +if (ds_eod) ds_cmd_done (1, DS1_OK); /* done? */ +else if (ds_eoc) ds_next_cyl (uptr); /* end cyl? seek */ +else sim_activate (uptr, ds_rtime); /* normal transfer */ return; } @@ -1332,11 +1357,11 @@ return; t_stat ds_set_uncorr (UNIT *uptr) { -sim_cancel (uptr); /* cancel any operation */ -ds_cmd_done (1, DS1_UNCOR); /* done with error */ -perror ("DS I/O error"); /* visible error */ +sim_cancel (uptr); /* cancel any operation */ +ds_cmd_done (1, DS1_UNCOR); /* done with error */ +perror ("DS I/O error"); /* visible error */ clearerr (uptr->fileref); -ds_poll (); /* force poll */ +ds_poll (); /* force poll */ return SCPE_IOERR; } @@ -1369,30 +1394,30 @@ ds_fifo_ip = ds_fifo_rp = ds_fifo_cnt = 0; for (i = 0; i < DS_FIFO_SIZE; i++) ds_fifo[i] = 0; return; } - + /* Reset routine */ t_stat ds_reset_cmn (DEVICE *dptr) { int32 i; -ds_cmd = 0; /* clear command */ -ds_cmdf = ds_cmdp = 0; /* clear commands flops */ -ds_fifo_reset (); /* clear fifo */ +ds_cmd = 0; /* clear command */ +ds_cmdf = ds_cmdp = 0; /* clear commands flops */ +ds_fifo_reset (); /* clear fifo */ ds_eoc = ds_eod = 0; ds_busy = 0; -ds_state = DS_IDLE; /* ctrl idle */ +ds_state = DS_IDLE; /* ctrl idle */ ds_lastatn = 0; ds_fmask = 0; ds_ptr = 0; ds_cyl = ds_hs = 0; ds_vctr = 0; -for (i = 0; i < DS_NUMDR; i++) { /* loop thru drives */ - sim_cancel (&ds_unit[i]); /* cancel activity */ - ds_unit[i].FNC = 0; /* clear function */ - ds_unit[i].CYL = 0; - ds_unit[i].STA = 0; - } +for (i = 0; i < DS_NUMDR; i++) { /* loop thru drives */ + sim_cancel (&ds_unit[i]); /* cancel activity */ + ds_unit[i].FNC = 0; /* clear function */ + ds_unit[i].CYL = 0; + ds_unit[i].STA = 0; + } sim_cancel (&ds_ctrl); sim_cancel (&ds_timer); return SCPE_OK; @@ -1400,12 +1425,12 @@ return SCPE_OK; t_stat ds_reset (DEVICE *dptr) { -ds_dib.cmd = 0; /* clear cmd */ -ds_dib.ctl = 0; /* clear ctl */ -ds_dib.fbf = 1; /* set fbf */ -ds_dib.flg = 1; /* set flg */ -ds_dib.srq = 0; /* clear srq */ -return ds_reset_cmn (dptr); /* do common reset */ +ds_dib.cmd = 0; /* clear cmd */ +ds_dib.ctl = 0; /* clear ctl */ +ds_dib.fbf = 1; /* set fbf */ +ds_dib.flg = 1; /* set flg */ +ds_dib.srq = 0; /* clear srq */ +return ds_reset_cmn (dptr); /* do common reset */ } /* Device attach */ @@ -1416,19 +1441,19 @@ 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? */ -ds_load_unload (uptr, 0, NULL, NULL); /* if OK, load heads */ -ds_sched_atn (uptr); /* schedule attention */ -if (((uptr->flags & UNIT_AUTO) == 0) || /* static size? */ - ((p = sim_fsize (uptr->fileref)) == 0)) return SCPE_OK; /* new file? */ -for (i = 0; drv_tab[i].sc != 0; i++) { /* find best fit */ - if (p <= (drv_tab[i].size * sizeof (uint16))) { - uptr->flags = (uptr->flags & ~UNIT_DTYPE) | (i << UNIT_V_DTYPE); - uptr->capac = drv_tab[i].size; - return SCPE_OK; - } - } +r = attach_unit (uptr, cptr); /* attach unit */ +if (r != SCPE_OK) return r; /* error? */ +ds_load_unload (uptr, 0, NULL, NULL); /* if OK, load heads */ +ds_sched_atn (uptr); /* schedule attention */ +if (((uptr->flags & UNIT_AUTO) == 0) || /* static size? */ + ((p = sim_fsize (uptr->fileref)) == 0)) return SCPE_OK; /* new file? */ +for (i = 0; drv_tab[i].sc != 0; i++) { /* find best fit */ + if (p <= (drv_tab[i].size * sizeof (uint16))) { + uptr->flags = (uptr->flags & ~UNIT_DTYPE) | (i << UNIT_V_DTYPE); + uptr->capac = drv_tab[i].size; + return SCPE_OK; + } + } return SCPE_OK; } @@ -1436,8 +1461,8 @@ return SCPE_OK; t_stat ds_detach (UNIT *uptr) { -if (!(uptr->flags & UNIT_ATT)) return SCPE_OK; /* attached? */ -ds_load_unload (uptr, UNIT_UNLOAD, NULL, NULL); /* unload heads */ +if (!(uptr->flags & UNIT_ATT)) return SCPE_OK; /* attached? */ +ds_load_unload (uptr, UNIT_UNLOAD, NULL, NULL); /* unload heads */ return detach_unit (uptr); } @@ -1445,14 +1470,16 @@ return detach_unit (uptr); t_stat ds_load_unload (UNIT *uptr, int32 value, char *cptr, void *desc) { -if ((uptr->flags & UNIT_ATT) == 0) return SCPE_UNATT; /* must be attached to [un]load */ -if (value == UNIT_UNLOAD) { /* unload heads? */ - uptr->flags = uptr->flags | UNIT_UNLOAD; /* indicate unload */ - uptr->STA = DS2_ATN; /* update drive status */ - ds_sched_atn (uptr); } /* schedule attention */ -else { /* load heads */ - uptr->flags = uptr->flags & ~UNIT_UNLOAD; /* indicate load */ - uptr->STA = DS2_ATN | DS2_FS; } /* update drive status */ +if ((uptr->flags & UNIT_ATT) == 0) return SCPE_UNATT; /* must be attached to [un]load */ +if (value == UNIT_UNLOAD) { /* unload heads? */ + uptr->flags = uptr->flags | UNIT_UNLOAD; /* indicate unload */ + uptr->STA = DS2_ATN; /* update drive status */ + ds_sched_atn (uptr); /* schedule attention */ + } +else { /* load heads */ + uptr->flags = uptr->flags & ~UNIT_UNLOAD; /* indicate load */ + uptr->STA = DS2_ATN | DS2_FS; /* update drive status */ + } return SCPE_OK; } @@ -1463,11 +1490,11 @@ void ds_sched_atn (UNIT *uptr) int32 i; if (!ds_dib.ctl || (sim_switches & SIM_SW_REST)) return; -for (i = 0; i < (DS_NUMDR + 1); i++) { /* check units, ctrl */ - if (sim_is_active (ds_dev.units + i)) return; - } -uptr->FNC = DSC_ATN; /* pseudo operation */ -sim_activate (uptr, 1); /* do immediately */ +for (i = 0; i < (DS_NUMDR + 1); i++) { /* check units, ctrl */ + if (sim_is_active (ds_dev.units + i)) return; + } +uptr->FNC = DSC_ATN; /* pseudo operation */ +sim_activate (uptr, 1); /* do immediately */ return; } @@ -1483,79 +1510,79 @@ return SCPE_OK; /* 13037 bootstrap routine (HP 12992B ROM) */ const uint16 ds_rom[IBL_LNT] = { - 0017727, /* STRT JSB STAT ; get status */ - 0002021, /* SSA,RSS ; is drive ready? */ - 0027742, /* JMP DMA ; yes, set up DMA */ - 0013714, /* AND B20 ; no, check status bits */ - 0002002, /* SZA ; faulty or hard down? */ - 0102030, /* HLT 30B ; HALT 30B */ - 0027700, /* JMP STRT ; try again */ - 0102011, /* ADR1 OCT 102011 */ - 0102055, /* ADR2 OCT 102055 */ - 0164000, /* CNT DEC -6144 */ - 0000007, /* D7 OCT 7 */ - 0001400, /* STCM OCT 1400 */ - 0000020, /* B20 OCT 20 */ - 0017400, /* STMS OCT 17400 */ - 0000000, /* 9 NOP's */ - 0000000, - 0000000, - 0000000, - 0000000, - 0000000, - 0000000, - 0000000, - 0000000, - 0000000, /* STAT NOP ; status check routine */ - 0107710, /* CLC DC,C ; set command mode */ - 0063713, /* LDA STCM ; get status command */ - 0102610, /* OTA DC ; output status command */ - 0102310, /* SFS DC ; wait for stat#1 word */ - 0027733, /* JMP *-1 */ - 0107510, /* LIB DC,C ; B-reg - status#1 word */ - 0102310, /* SFS DC ; wait for stat#2 word */ - 0027736, /* JMP *-1 */ - 0103510, /* LIA DC,C ; A-reg - status#2 word */ - 0127727, /* JMP STAT,I ; return */ - 0067776, /* DMA LDB DMAC ; get DMA control word */ - 0106606, /* OTB 6 ; output DMA ctrl word */ - 0067707, /* LDB ADR1 ; get memory address */ - 0106702, /* CLC 2 ; set memory addr mode */ - 0106602, /* OTB 2 ; output mem addr to DMA */ - 0102702, /* STC 2 ; set word count mode */ - 0067711, /* LDB CNT ; get word count */ - 0106602, /* OTB 2 ; output word cnt to DMA */ - 0106710, /* CLC CLC DC ; set command follows */ - 0102501, /* LIA 1 ; load switches */ - 0106501, /* LIB 1 ; register settings */ - 0013712, /* AND D7 ; isolate head number */ - 0005750, /* BLF,CLE,SLB ; bit 12 = 0? */ - 0027762, /* JMP *+3 ; no, manual boot */ - 0002002, /* SZA ; yes, RPL, head# = 0? */ - 0001000, /* ALS ; no, head# = 1 --> 2 */ - 0001720, /* ALF,ALS ; form cold load */ - 0001000, /* ALS ; command word */ - 0103706, /* STC 6,C ; activate DMA */ - 0103610, /* OTA DC,C ; output cold load cmd */ - 0102310, /* SFS DC ; is cold load done? */ - 0027766, /* JMP *-1 ; no, wait */ - 0017727, /* JSB STAT ; yes, get status */ - 0060001, /* LDA 1 ; get status word #1 */ - 0013715, /* AND STMS ; isolate status bits */ - 0002002, /* SZA ; is transfer ok? */ - 0027700, /* JMP STRT ; no, try again */ - 0117710, /* JSB ADR2,I ; yes, start program */ - 0000010, /* DMAC ABS DC ; DMA command word */ - 0170100, /* ABS -STRT */ -}; + 0017727, /* STRT JSB STAT ; get status */ + 0002021, /* SSA,RSS ; is drive ready? */ + 0027742, /* JMP DMA ; yes, set up DMA */ + 0013714, /* AND B20 ; no, check status bits */ + 0002002, /* SZA ; faulty or hard down? */ + 0102030, /* HLT 30B ; HALT 30B */ + 0027700, /* JMP STRT ; try again */ + 0102011, /* ADR1 OCT 102011 */ + 0102055, /* ADR2 OCT 102055 */ + 0164000, /* CNT DEC -6144 */ + 0000007, /* D7 OCT 7 */ + 0001400, /* STCM OCT 1400 */ + 0000020, /* B20 OCT 20 */ + 0017400, /* STMS OCT 17400 */ + 0000000, /* 9 NOP's */ + 0000000, + 0000000, + 0000000, + 0000000, + 0000000, + 0000000, + 0000000, + 0000000, + 0000000, /* STAT NOP ; status check routine */ + 0107710, /* CLC DC,C ; set command mode */ + 0063713, /* LDA STCM ; get status command */ + 0102610, /* OTA DC ; output status command */ + 0102310, /* SFS DC ; wait for stat#1 word */ + 0027733, /* JMP *-1 */ + 0107510, /* LIB DC,C ; B-reg - status#1 word */ + 0102310, /* SFS DC ; wait for stat#2 word */ + 0027736, /* JMP *-1 */ + 0103510, /* LIA DC,C ; A-reg - status#2 word */ + 0127727, /* JMP STAT,I ; return */ + 0067776, /* DMA LDB DMAC ; get DMA control word */ + 0106606, /* OTB 6 ; output DMA ctrl word */ + 0067707, /* LDB ADR1 ; get memory address */ + 0106702, /* CLC 2 ; set memory addr mode */ + 0106602, /* OTB 2 ; output mem addr to DMA */ + 0102702, /* STC 2 ; set word count mode */ + 0067711, /* LDB CNT ; get word count */ + 0106602, /* OTB 2 ; output word cnt to DMA */ + 0106710, /* CLC CLC DC ; set command follows */ + 0102501, /* LIA 1 ; load switches */ + 0106501, /* LIB 1 ; register settings */ + 0013712, /* AND D7 ; isolate head number */ + 0005750, /* BLF,CLE,SLB ; bit 12 = 0? */ + 0027762, /* JMP *+3 ; no, manual boot */ + 0002002, /* SZA ; yes, RPL, head# = 0? */ + 0001000, /* ALS ; no, head# = 1 --> 2 */ + 0001720, /* ALF,ALS ; form cold load */ + 0001000, /* ALS ; command word */ + 0103706, /* STC 6,C ; activate DMA */ + 0103610, /* OTA DC,C ; output cold load cmd */ + 0102310, /* SFS DC ; is cold load done? */ + 0027766, /* JMP *-1 ; no, wait */ + 0017727, /* JSB STAT ; yes, get status */ + 0060001, /* LDA 1 ; get status word #1 */ + 0013715, /* AND STMS ; isolate status bits */ + 0002002, /* SZA ; is transfer ok? */ + 0027700, /* JMP STRT ; no, try again */ + 0117710, /* JSB ADR2,I ; yes, start program */ + 0000010, /* DMAC ABS DC ; DMA command word */ + 0170100, /* ABS -STRT */ + }; t_stat ds_boot (int32 unitno, DEVICE *dptr) { int32 dev; -if (unitno != 0) return SCPE_NOFNC; /* only unit 0 */ -dev = ds_dib.devno; /* get data chan dev */ -if (ibl_copy (ds_rom, dev)) return SCPE_IERR; /* copy boot to memory */ +if (unitno != 0) return SCPE_NOFNC; /* only unit 0 */ +dev = ds_dib.devno; /* get data chan dev */ +if (ibl_copy (ds_rom, dev)) return SCPE_IERR; /* copy boot to memory */ SR = (SR & (IBL_OPT | IBL_DS_HEAD)) | IBL_DS | IBL_MAN | (dev << IBL_V_DEV); return SCPE_OK; } diff --git a/HP2100/hp2100_fp.c b/HP2100/hp2100_fp.c index 77216138..613aca63 100644 --- a/HP2100/hp2100_fp.c +++ b/HP2100/hp2100_fp.c @@ -19,15 +19,16 @@ 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 + 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-Feb-05 JDB Added FFP helpers f_pack, f_unpack, f_pwr2 - 11-Feb-05 JDB Fixed missing negative overflow renorm in StoreFP - 26-Dec-04 RMS Separated A/B from M[0/1] for DMA IO (from Dave Bryan) - 15-Jul-03 RMS Fixed signed/unsigned warning - 21-Oct-02 RMS Recoded for compatibility with 21MX microcode algorithms + 22-Jul-05 RMS Fixed compiler warning in Solaris (from Doug Glyn) + 25-Feb-05 JDB Added FFP helpers f_pack, f_unpack, f_pwr2 + 11-Feb-05 JDB Fixed missing negative overflow renorm in StoreFP + 26-Dec-04 RMS Separated A/B from M[0/1] for DMA IO (from Dave Bryan) + 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: @@ -39,18 +40,18 @@ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ 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 + 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 + 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 @@ -66,44 +67,45 @@ - "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 */ +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_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 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 FPAB ((((uint32) AR) << 16) | ((uint32) BR)) -#define DMASK32 0xFFFFFFFF +#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_ARS(v,s) (((v) >> (s)) | (((v) & FP_SIGN)? \ + (((uint32) DMASK32) << (32 - (s))): 0)) & DMASK32 -#define FR_NEG(v) ((~(v) + 1) & DMASK32) +#define FR_NEG(v) ((~(v) + 1) & DMASK32) extern uint16 ABREG[2]; @@ -111,7 +113,7 @@ 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) @@ -119,20 +121,23 @@ 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 */ +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 */ +if ((AR & SIGN) && ((fop.fr | res) & DMASK)) /* any low bits lost? */ + AR = (AR + 1) & DMASK; /* round up */ return 0; } @@ -140,13 +145,13 @@ return 0; uint32 f_flt (void) { -struct ufp res = { 15, 0 }; /* +, 2**15 */ +struct ufp res = { 15, 0 }; /* +, 2**15 */ -res.fr = ((uint32) AR) << 16; /* left justify */ -StoreFP (&res); /* store result */ -return 0; /* clr overflow */ +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) @@ -154,37 +159,43 @@ 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 */ +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 */ @@ -195,19 +206,20 @@ 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 */ +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 */ @@ -217,10 +229,10 @@ 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 */ +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; @@ -235,33 +247,34 @@ 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 */ +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 */ } - + /* Fast FORTRAN Processor helpers. */ /* Pack mantissa in A/B and exponent and return fp in A/B */ @@ -279,9 +292,9 @@ return StoreFP (&fop); void f_unpack (void) { -AR = FP_GETEXP (BR); /* get exponent */ -if (FP_GETEXPS (BR)) AR = (AR | ~FP_M_EXP) & DMASK; /* < 0? sext */ -BR = BR & (uint16) ~(FP_EXP | FP_EXPS); /* clear exp */ +AR = FP_GETEXP (BR); /* get exponent */ +if (FP_GETEXPS (BR)) AR = (AR | ~FP_M_EXP) & DMASK; /* < 0? sext */ +BR = BR & (uint16) ~(FP_EXP | FP_EXPS); /* clear exp */ return; } @@ -292,38 +305,41 @@ void f_pwr2 (int32 n) { uint32 save_a; -if (AR | BR) { /* microcode test */ - save_a = AR; - f_unpack (); /* unpack exponent */ - AR = AR + n; /* multiply */ - BR = BR | ((AR & FP_M_EXP) << FP_V_EXP) | /* merge exponent */ - ((AR & SIGN)? (1 << FP_V_EXPS): 0); /* and exponent sign */ - AR = save_a; } +if (AR | BR) { /* microcode test */ + save_a = AR; + f_unpack (); /* unpack exponent */ + AR = AR + n; /* multiply */ + BR = BR | ((AR & FP_M_EXP) << FP_V_EXP) | /* merge exponent */ + ((AR & SIGN)? (1 << FP_V_EXPS): 0); /* and exponent sign */ + AR = save_a; + } return; } - + /* 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 */ +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 */ +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; } @@ -333,24 +349,27 @@ 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; /* renormalize */ - fop->exp = fop->exp + 1; } -else NormFP (fop); /* check for norm */ -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 */ +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; /* renormalize */ + fop->exp = fop->exp + 1; + } +else NormFP (fop); /* check for norm */ +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_fp1.c b/HP2100/hp2100_fp1.c index 3f61004a..025c5818 100644 --- a/HP2100/hp2100_fp1.c +++ b/HP2100/hp2100_fp1.c @@ -19,15 +19,15 @@ 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 + 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. Primary references: - HP 1000 M/E/F-Series Computers Technical Reference Handbook - (5955-0282, Mar-1980) + (5955-0282, Mar-1980) - DOS/RTE Relocatable Library Reference Manual - (24998-90001, Oct-1981) + (24998-90001, Oct-1981) The extended-precision floating-point format is a 48-bit extension of the 32-bit format used for single precision. A packed "XP" number consists of a @@ -52,78 +52,80 @@ 64-bit mantissa and a signed 32-bit exponent. The mantissa is masked to 48 bits and left-justified, while the exponent is right-justified. */ - + #include "hp2100_defs.h" #include "hp2100_cpu.h" #include "hp2100_fp1.h" -#if defined (HAVE_INT64) /* we need int64 support */ +#if defined (HAVE_INT64) /* we need int64 support */ /* packed starting bit numbers */ -#define XP_PAD 16 /* padding LSBs */ +#define XP_PAD 16 /* padding LSBs */ -#define XP_V_MSIGN (47 + XP_PAD) /* mantissa sign */ -#define XP_V_MANT ( 8 + XP_PAD) /* mantissa */ -#define XP_V_EXP ( 1 + XP_PAD) /* exponent */ -#define XP_V_ESIGN ( 0 + XP_PAD) /* exponent sign */ +#define XP_V_MSIGN (47 + XP_PAD) /* mantissa sign */ +#define XP_V_MANT ( 8 + XP_PAD) /* mantissa */ +#define XP_V_EXP ( 1 + XP_PAD) /* exponent */ +#define XP_V_ESIGN ( 0 + XP_PAD) /* exponent sign */ /* packed bit widths */ -#define XP_W_MSIGN 1 /* mantissa sign */ -#define XP_W_MANT 39 /* mantissa */ -#define XP_W_EXP 7 /* exponent */ -#define XP_W_ESIGN 1 /* exponent sign */ +#define XP_W_MSIGN 1 /* mantissa sign */ +#define XP_W_MANT 39 /* mantissa */ +#define XP_W_EXP 7 /* exponent */ +#define XP_W_ESIGN 1 /* exponent sign */ /* packed bit masks */ -#define XP_M_MSIGN (((t_uint64) 1 << XP_W_MSIGN) - 1) /* mantissa sign */ -#define XP_M_MANT (((t_uint64) 1 << XP_W_MANT) - 1) /* mantissa */ -#define XP_M_EXP (((t_uint64) 1 << XP_W_EXP) - 1) /* exponent */ -#define XP_M_ESIGN (((t_uint64) 1 << XP_W_ESIGN) - 1) /* exponent sign */ +#define XP_M_MSIGN (((t_uint64) 1 << XP_W_MSIGN) - 1) /* mantissa sign */ +#define XP_M_MANT (((t_uint64) 1 << XP_W_MANT) - 1) /* mantissa */ +#define XP_M_EXP (((t_uint64) 1 << XP_W_EXP) - 1) /* exponent */ +#define XP_M_ESIGN (((t_uint64) 1 << XP_W_ESIGN) - 1) /* exponent sign */ /* packed field masks */ -#define XP_MSIGN (XP_M_MSIGN << XP_V_MSIGN) /* mantissa sign */ -#define XP_MANT (XP_M_MANT << XP_V_MANT) /* mantissa */ -#define XP_SMANT (XP_MSIGN | XP_MANT) /* signed mantissa */ +#define XP_MSIGN (XP_M_MSIGN << XP_V_MSIGN) /* mantissa sign */ +#define XP_MANT (XP_M_MANT << XP_V_MANT) /* mantissa */ +#define XP_SMANT (XP_MSIGN | XP_MANT) /* signed mantissa */ /* unpacked starting bit numbers */ -#define XP_V_UMANT (0 + XP_PAD) /* signed mantissa */ +#define XP_V_UMANT (0 + XP_PAD) /* signed mantissa */ /* unpacked bit widths */ -#define XP_W_USMANT 48 /* signed mantissa */ +#define XP_W_USMANT 48 /* signed mantissa */ /* unpacked bit masks */ -#define XP_M_USMANT (((t_uint64) 1 << XP_W_USMANT) - 1) /* mantissa */ +#define XP_M_USMANT (((t_uint64) 1 << XP_W_USMANT) - 1) /* mantissa */ /* unpacked field masks */ -#define XP_USMANT (XP_M_USMANT << XP_V_UMANT) /* signed mantissa */ +#define XP_USMANT (XP_M_USMANT << XP_V_UMANT) /* signed mantissa */ /* values */ -#define XP_ONEHALF ((t_int64) 1 << (XP_V_MSIGN - 1)) /* mantissa = 0.5 */ -#define XP_HALSBPOS ((t_int64) 1 << (XP_V_MANT - 1)) /* + 1/2 LSB */ -#define XP_HALSBNEG ((t_int64) XP_HALSBPOS - 1) /* - 1/2 LSB */ -#define XP_MAXPOS ((t_int64) XP_MANT) /* maximum pos mantissa */ -#define XP_MAXNEG ((t_int64) XP_MSIGN) /* maximum neg mantissa */ -#define XP_MAXEXP ((t_int64) XP_M_EXP) /* maximum pos exponent */ +#define XP_ONEHALF ((t_int64) 1 << (XP_V_MSIGN - 1)) /* mantissa = 0.5 */ +#define XP_HALSBPOS ((t_int64) 1 << (XP_V_MANT - 1)) /* + 1/2 LSB */ +#define XP_HALSBNEG ((t_int64) XP_HALSBPOS - 1) /* - 1/2 LSB */ +#define XP_MAXPOS ((t_int64) XP_MANT) /* maximum pos mantissa */ +#define XP_MAXNEG ((t_int64) XP_MSIGN) /* maximum neg mantissa */ +#define XP_MAXEXP ((t_int64) XP_M_EXP) /* maximum pos exponent */ /* helpers */ -#define DENORM(x) ((((x) ^ (x) << 1) & XP_MSIGN) == 0) +#define DENORM(x) ((((x) ^ (x) << 1) & XP_MSIGN) == 0) -#define TO_INT64(xpn) ((t_int64) ((t_uint64) (xpn).high << 32 | (xpn).low)) +#define TO_INT64(xpn) ((t_int64) ((t_uint64) (xpn).high << 32 | (xpn).low)) /* internal unpacked extended-precision representation */ -typedef struct { t_int64 mantissa; - int32 exponent; } XPU; - +typedef struct { + t_int64 mantissa; + int32 exponent; + } XPU; + /* Private routines */ @@ -145,7 +147,7 @@ static XPU unpack (XPN packed) { XPU unpacked; -unpacked.mantissa = TO_INT64 (packed) & XP_SMANT; /* left-justify mantissa */ +unpacked.mantissa = TO_INT64 (packed) & XP_SMANT; /* left-justify mantissa */ unpacked.exponent = (int8) ((packed.low >> XP_V_EXP & XP_M_EXP) | /* sign-extend exponent */ packed.low >> (XP_V_ESIGN - XP_W_EXP)); @@ -157,11 +159,13 @@ return unpacked; static void normalize (XPU *unpacked) { -if (unpacked->mantissa) { /* non-zero? */ - while (DENORM (unpacked->mantissa)) { /* normal form? */ - unpacked->exponent = unpacked->exponent - 1; /* no, so shift */ - unpacked->mantissa = unpacked->mantissa << 1; } } -else unpacked->exponent = 0; /* clean for zero */ +if (unpacked->mantissa) { /* non-zero? */ + while (DENORM (unpacked->mantissa)) { /* normal form? */ + unpacked->exponent = unpacked->exponent - 1; /* no, so shift */ + unpacked->mantissa = unpacked->mantissa << 1; + } + } +else unpacked->exponent = 0; /* clean for zero */ return; } @@ -172,25 +176,28 @@ static uint32 pack (XPN *packed, XPU unpacked) { int32 sign, overflow = 0; -normalize (&unpacked); /* normalize */ -sign = (unpacked.mantissa < 0); /* save sign */ -unpacked.mantissa = (unpacked.mantissa + /* round the number */ - (sign? XP_HALSBNEG: XP_HALSBPOS)) & XP_SMANT; /* mask off rounding bits */ -if (sign != (unpacked.mantissa < 0)) { /* pos overflow? */ - unpacked.mantissa = /* renormalize */ - (t_uint64) unpacked.mantissa >> 1 & XP_SMANT; /* and remask */ - unpacked.exponent = unpacked.exponent + 1; } -else normalize (&unpacked); /* neg overflow? renorm */ +normalize (&unpacked); /* normalize */ +sign = (unpacked.mantissa < 0); /* save sign */ +unpacked.mantissa = (unpacked.mantissa + /* round the number */ + (sign? XP_HALSBNEG: XP_HALSBPOS)) & XP_SMANT; /* mask off rounding bits */ +if (sign != (unpacked.mantissa < 0)) { /* pos overflow? */ + unpacked.mantissa = /* renormalize */ + (t_uint64) unpacked.mantissa >> 1 & XP_SMANT; /* and remask */ + unpacked.exponent = unpacked.exponent + 1; + } +else normalize (&unpacked); /* neg overflow? renorm */ unpacked.mantissa = unpacked.mantissa & XP_SMANT; -if (unpacked.mantissa == 0) /* result 0? */ - packed->high = packed->low = 0; /* return 0 */ -else if (unpacked.exponent < -(XP_MAXEXP + 1)) { /* underflow? */ - packed->high = packed->low = 0; /* return 0 */ - overflow = 1; } /* and set overflow */ -else if (unpacked.exponent > XP_MAXEXP) { /* overflow? */ - if (sign) *packed = to_xpn (XP_MAXNEG, XP_MAXEXP); /* return neg infinity */ - else *packed = to_xpn (XP_MAXPOS, XP_MAXEXP); /* or pos infinity */ - overflow = 1; } /* with overflow */ +if (unpacked.mantissa == 0) /* result 0? */ + packed->high = packed->low = 0; /* return 0 */ +else if (unpacked.exponent < -(XP_MAXEXP + 1)) { /* underflow? */ + packed->high = packed->low = 0; /* return 0 */ + overflow = 1; /* and set overflow */ + } +else if (unpacked.exponent > XP_MAXEXP) { /* overflow? */ + if (sign) *packed = to_xpn (XP_MAXNEG, XP_MAXEXP); /* return neg infinity */ + else *packed = to_xpn (XP_MAXPOS, XP_MAXEXP); /* or pos infinity */ + overflow = 1; /* with overflow */ + } else *packed = to_xpn (unpacked.mantissa, unpacked.exponent); return overflow; } @@ -200,10 +207,11 @@ return overflow; static void complement (XPU *result) { -result->mantissa = -result->mantissa; /* negate mantissa */ -if (result->mantissa == XP_MAXNEG) { /* maximum negative? */ - result->mantissa = (t_uint64) result->mantissa >> 1; /* renormalize to pos */ - result->exponent = result->exponent + 1; } /* correct exponent */ +result->mantissa = -result->mantissa; /* negate mantissa */ +if (result->mantissa == XP_MAXNEG) { /* maximum negative? */ + result->mantissa = (t_uint64) result->mantissa >> 1; /* renormalize to pos */ + result->exponent = result->exponent + 1; /* correct exponent */ + } return; } @@ -222,24 +230,29 @@ static void add (XPU *sum, XPU augend, XPU addend) { int32 magn; -if (augend.mantissa == 0) *sum = addend; /* x + 0 = x */ -else if (addend.mantissa == 0) *sum = augend; /* 0 + x = x */ +if (augend.mantissa == 0) *sum = addend; /* x + 0 = x */ +else if (addend.mantissa == 0) *sum = augend; /* 0 + x = x */ else { - magn = augend.exponent - addend.exponent; /* difference exponents */ - if (magn > 0) { /* addend smaller? */ - *sum = augend; /* preset augend */ - addend.mantissa = addend.mantissa >> magn; } /* align addend */ - else { /* augend smaller? */ - *sum = addend; /* preset addend */ - magn = -magn; /* make difference positive */ - augend.mantissa = augend.mantissa >> magn; } /* align augend */ - if (magn <= XP_W_MANT + 1) { /* check mangitude */ - sum->mantissa = addend.mantissa + augend.mantissa; /* add mantissas */ - if (((addend.mantissa < 0) == (augend.mantissa < 0)) && /* chk overflow */ - ((addend.mantissa < 0) != (sum->mantissa < 0))) { - sum->mantissa = (addend.mantissa & XP_MSIGN) | /* restore sign */ - (t_uint64) sum->mantissa >> 1; /* renormalize */ - sum->exponent = sum->exponent + 1; } } } /* adjust exponent */ + magn = augend.exponent - addend.exponent; /* difference exponents */ + if (magn > 0) { /* addend smaller? */ + *sum = augend; /* preset augend */ + addend.mantissa = addend.mantissa >> magn; /* align addend */ + } + else { /* augend smaller? */ + *sum = addend; /* preset addend */ + magn = -magn; /* make difference positive */ + augend.mantissa = augend.mantissa >> magn; /* align augend */ + } + if (magn <= XP_W_MANT + 1) { /* check mangitude */ + sum->mantissa = addend.mantissa + augend.mantissa; /* add mantissas */ + if (((addend.mantissa < 0) == (augend.mantissa < 0)) && /* chk overflow */ + ((addend.mantissa < 0) != (sum->mantissa < 0))) { + sum->mantissa = (addend.mantissa & XP_MSIGN) | /* restore sign */ + (t_uint64) sum->mantissa >> 1; /* renormalize */ + sum->exponent = sum->exponent + 1; /* adjust exponent */ + } + } + } return; } @@ -252,27 +265,27 @@ return; multiplicand "a1a2a3" and a 48-bit multiplier "b1b2b3", the firmware performs these calculations to develop a 48-bit product: - a1 a2 a3 - +-------+-------+-------+ - b1 b2 b3 - +-------+-------+-------+ - _________________________ + a1 a2 a3 + +-------+-------+-------+ + b1 b2 b3 + +-------+-------+-------+ + _________________________ - a1 * b3 [m1] - +-------+-------+ - a2 * b2 [m2] - +-------+-------+ - a1 * b2 [m3] - +-------+-------+ - a3 * b1 [m4] - +-------+-------+ - a2 * b1 [m5] - +-------+-------+ - a1 * b1 [m6] + a1 * b3 [m1] + +-------+-------+ + a2 * b2 [m2] + +-------+-------+ + a1 * b2 [m3] + +-------+-------+ + a3 * b1 [m4] + +-------+-------+ + a2 * b1 [m5] + +-------+-------+ + a1 * b1 [m6] +-------+-------+ _________________________________ - product + product +-------+-------+-------+ The least-significant words of intermediate multiplications [m1], [m2], and @@ -289,34 +302,36 @@ uint32 ah, al, bh, bl, carry, sign = 0; t_uint64 hi, m1, m2, m3; if ((multiplicand.mantissa == 0) || (multiplier.mantissa == 0)) /* x * 0 = 0 */ - product->mantissa = product->exponent = 0; + product->mantissa = product->exponent = 0; else { - if (multiplicand.mantissa < 0) { /* negative? */ - complement (&multiplicand); /* complement operand */ - sign = ~sign; } /* track sign */ - if (multiplier.mantissa < 0) { /* negative? */ - complement (&multiplier); /* complement operand */ - sign = ~sign; } /* track sign */ + if (multiplicand.mantissa < 0) { /* negative? */ + complement (&multiplicand); /* complement operand */ + sign = ~sign; /* track sign */ + } + if (multiplier.mantissa < 0) { /* negative? */ + complement (&multiplier); /* complement operand */ + sign = ~sign; /* track sign */ + } + product->exponent = multiplicand.exponent + /* compute exponent */ + multiplier.exponent + 1; - product->exponent = multiplicand.exponent + /* compute exponent */ - multiplier.exponent + 1; + ah = (uint32) (multiplicand.mantissa >> 32); /* split multiplicand */ + al = (uint32) multiplicand.mantissa; /* into high and low parts */ + bh = (uint32) (multiplier.mantissa >> 32); /* split multiplier */ + bl = (uint32) multiplier.mantissa; /* into high and low parts */ - ah = (uint32) (multiplicand.mantissa >> 32); /* split multiplicand */ - al = (uint32) multiplicand.mantissa; /* into high and low parts */ - bh = (uint32) (multiplier.mantissa >> 32); /* split multiplier */ - bl = (uint32) multiplier.mantissa; /* into high and low parts */ + hi = ((t_uint64) ah * bh); /* form four cross products */ + m1 = ((t_uint64) ah * bl); /* using 32 x 32 = 64-bit */ + m2 = ((t_uint64) al * bh); /* hardware multiplies */ + m3 = ((t_uint64) al * bl); - hi = ((t_uint64) ah * bh); /* form four cross products */ - m1 = ((t_uint64) ah * bl); /* using 32 x 32 = 64-bit */ - m2 = ((t_uint64) al * bh); /* hardware multiplies */ - m3 = ((t_uint64) al * bl); + carry = ((uint32) m1 + (uint32) m2 + /* form a carry bit */ + (uint32) (m3 >> 32)) >> (31 - XP_V_UMANT); /* and align to LSB - 1 */ - carry = ((uint32) m1 + (uint32) m2 + /* form a carry bit */ - (uint32) (m3 >> 32)) >> (31 - XP_V_UMANT); /* and align to LSB - 1 */ - - product->mantissa = (hi + (m1 >> 32) + /* align, sum, and mask */ - (m2 >> 32) + carry) & XP_USMANT; - if (sign) complement (product); } /* negate if required */ + product->mantissa = (hi + (m1 >> 32) + /* align, sum, and mask */ + (m2 >> 32) + carry) & XP_USMANT; + if (sign) complement (product); /* negate if required */ + } return; } @@ -332,32 +347,33 @@ static void divide (XPU *quotient, XPU dividend, XPU divisor) { t_int64 bh, bl, m1, m2, m3, m4; -if (divisor.mantissa == 0) { /* division by zero? */ - if (dividend.mantissa < 0) - quotient->mantissa = XP_MSIGN; /* return minus infinity */ - else quotient->mantissa = XP_MANT; /* or plus infinity */ - quotient->exponent = XP_MAXEXP + 1; } -else if (dividend.mantissa == 0) /* dividend zero? */ - quotient->mantissa = quotient->exponent = 0; /* yes; result is zero */ +if (divisor.mantissa == 0) { /* division by zero? */ + if (dividend.mantissa < 0) + quotient->mantissa = XP_MSIGN; /* return minus infinity */ + else quotient->mantissa = XP_MANT; /* or plus infinity */ + quotient->exponent = XP_MAXEXP + 1; + } +else if (dividend.mantissa == 0) /* dividend zero? */ + quotient->mantissa = quotient->exponent = 0; /* yes; result is zero */ else { - quotient->exponent = dividend.exponent - /* division subtracts exponents */ - divisor.exponent + 1; + quotient->exponent = dividend.exponent - /* division subtracts exponents */ + divisor.exponent + 1; - bh = divisor.mantissa >> 32; /* split divisor */ - bl = divisor.mantissa & 0xFFFFFFFF; + bh = divisor.mantissa >> 32; /* split divisor */ + bl = divisor.mantissa & 0xFFFFFFFF; - m1 = (dividend.mantissa >> 2) / bh; /* form 1st partial quotient */ - m2 = (dividend.mantissa >> 2) % bh; /* obtain remainder */ - m3 = bl * m1; /* calculate correction */ - m4 = ((m2 - (m3 >> 32)) << 32) / bh; /* form 2nd partial quotient */ + m1 = (dividend.mantissa >> 2) / bh; /* form 1st partial quotient */ + m2 = (dividend.mantissa >> 2) % bh; /* obtain remainder */ + m3 = bl * m1; /* calculate correction */ + m4 = ((m2 - (m3 >> 32)) << 32) / bh; /* form 2nd partial quotient */ - quotient->mantissa = (m1 << 32) + m4; /* merge quotients */ -} + quotient->mantissa = (m1 << 32) + m4; /* merge quotients */ + } return; } #endif - + /* Global routines */ /* Extended-precision memory read */ @@ -367,7 +383,7 @@ XPN ReadX (uint32 va) XPN packed; packed.high = ReadW (va) << 16 | ReadW ((va + 1) & VAMASK); -packed.low = ReadW ((va + 2) & VAMASK) << 16; /* read and pack */ +packed.low = ReadW ((va + 2) & VAMASK) << 16; /* read and pack */ return packed; } @@ -376,9 +392,9 @@ return packed; void WriteX (uint32 va, XPN packed) { -WriteW (va, (packed.high >> 16) & DMASK); /* write high word */ -WriteW ((va + 1) & VAMASK, packed.high & DMASK); /* write middle word */ -WriteW ((va + 2) & VAMASK, (packed.low >> 16) & DMASK); /* write low word */ +WriteW (va, (packed.high >> 16) & DMASK); /* write high word */ +WriteW ((va + 1) & VAMASK, packed.high & DMASK); /* write middle word */ +WriteW ((va + 2) & VAMASK, (packed.low >> 16) & DMASK); /* write low word */ } @@ -390,10 +406,10 @@ uint32 x_add (XPN *sum, XPN augend, XPN addend) { XPU usum, uaddend, uaugend; -uaugend = unpack (augend); /* unpack augend */ -uaddend = unpack (addend); /* unpack addend */ -add (&usum, uaugend, uaddend); /* calculate sum */ -return pack (sum, usum); /* pack sum */ +uaugend = unpack (augend); /* unpack augend */ +uaddend = unpack (addend); /* unpack addend */ +add (&usum, uaugend, uaddend); /* calculate sum */ +return pack (sum, usum); /* pack sum */ } @@ -403,10 +419,10 @@ uint32 x_sub (XPN *difference, XPN minuend, XPN subtrahend) { XPU udifference, uminuend, usubtrahend; -uminuend = unpack (minuend); /* unpack minuend */ -usubtrahend = unpack (subtrahend); /* unpack subtrahend */ -complement (&usubtrahend); /* calculate difference */ -add (&udifference, uminuend, usubtrahend); /* pack difference */ +uminuend = unpack (minuend); /* unpack minuend */ +usubtrahend = unpack (subtrahend); /* unpack subtrahend */ +complement (&usubtrahend); /* calculate difference */ +add (&udifference, uminuend, usubtrahend); /* pack difference */ return pack (difference, udifference); } @@ -417,10 +433,10 @@ uint32 x_mpy (XPN *product, XPN multiplicand, XPN multiplier) { XPU uproduct, umultiplicand, umultiplier; -umultiplicand = unpack (multiplicand); /* unpack multiplicand */ -umultiplier = unpack (multiplier); /* unpack multiplier */ -multiply (&uproduct, umultiplicand, umultiplier); /* calculate product */ -return pack (product, uproduct); /* pack product */ +umultiplicand = unpack (multiplicand); /* unpack multiplicand */ +umultiplier = unpack (multiplier); /* unpack multiplier */ +multiply (&uproduct, umultiplicand, umultiplier); /* calculate product */ +return pack (product, uproduct); /* pack product */ } @@ -430,10 +446,10 @@ uint32 x_div (XPN *quotient, XPN dividend, XPN divisor) { XPU uquotient, udividend, udivisor; -udividend = unpack (dividend); /* unpack dividend */ -udivisor = unpack (divisor); /* unpack divisor */ -divide (&uquotient, udividend, udivisor); /* calculate quotient */ -return pack (quotient, uquotient); /* pack quotient */ +udividend = unpack (dividend); /* unpack dividend */ +udivisor = unpack (divisor); /* unpack divisor */ +divide (&uquotient, udividend, udivisor); /* calculate quotient */ +return pack (quotient, uquotient); /* pack quotient */ } @@ -445,9 +461,9 @@ uint32 x_pak (XPN *result, XPN mantissa, int32 exponent) { XPU unpacked; -unpacked.mantissa = TO_INT64 (mantissa); /* retrieve mantissa */ -unpacked.exponent = exponent; /* and exponent */ -return pack (result, unpacked); /* pack them */ +unpacked.mantissa = TO_INT64 (mantissa); /* retrieve mantissa */ +unpacked.exponent = exponent; /* and exponent */ +return pack (result, unpacked); /* pack them */ } @@ -461,11 +477,11 @@ uint32 x_com (XPN *mantissa) { XPU unpacked; -unpacked.mantissa = TO_INT64 (*mantissa); /* retrieve mantissa */ -unpacked.exponent = 0; /* exponent is irrelevant */ -complement (&unpacked); /* negate it */ -*mantissa = to_xpn (unpacked.mantissa, 0); /* replace mantissa */ -return (uint32) unpacked.exponent; /* return exponent increment */ +unpacked.mantissa = TO_INT64 (*mantissa); /* retrieve mantissa */ +unpacked.exponent = 0; /* exponent is irrelevant */ +complement (&unpacked); /* negate it */ +*mantissa = to_xpn (unpacked.mantissa, 0); /* replace mantissa */ +return (uint32) unpacked.exponent; /* return exponent increment */ } @@ -475,9 +491,9 @@ uint32 x_dcm (XPN *packed) { XPU unpacked; -unpacked = unpack (*packed); /* unpack the number */ -complement (&unpacked); /* negate it */ -return pack (packed, unpacked); /* and repack */ +unpacked = unpack (*packed); /* unpack the number */ +complement (&unpacked); /* negate it */ +return pack (packed, unpacked); /* and repack */ } @@ -488,21 +504,22 @@ void x_trun (XPN *result, XPN source) t_uint64 mask; uint32 bitslost; XPU unpacked; -const XPU one = { XP_ONEHALF, 1 }; /* 0.5 * 2 ** 1 = 1.0 */ +const XPU one = { XP_ONEHALF, 1 }; /* 0.5 * 2 ** 1 = 1.0 */ unpacked = unpack (source); -if (unpacked.exponent < 0) /* number < 0.5? */ - result->high = result->low = 0; /* return 0 */ -else if (unpacked.exponent > XP_W_MANT) /* no fractional bits? */ - *result = source; /* already integer */ +if (unpacked.exponent < 0) /* number < 0.5? */ + result->high = result->low = 0; /* return 0 */ +else if (unpacked.exponent > XP_W_MANT) /* no fractional bits? */ + *result = source; /* already integer */ else { - mask = (XP_MANT >> unpacked.exponent) & XP_MANT;/* mask fractional bits */ - bitslost = (uint32) (unpacked.mantissa & mask); /* flag if bits lost */ - unpacked.mantissa = unpacked.mantissa & ~mask; /* mask off fraction */ - if ((unpacked.mantissa < 0) && bitslost) /* negative? */ - add (&unpacked, unpacked, one); /* truncate toward zero */ - pack (result, unpacked); } /* (overflow cannot occur) */ + mask = (XP_MANT >> unpacked.exponent) & XP_MANT; /* mask fractional bits */ + bitslost = (uint32) (unpacked.mantissa & mask); /* flag if bits lost */ + unpacked.mantissa = unpacked.mantissa & ~mask; /* mask off fraction */ + if ((unpacked.mantissa < 0) && bitslost) /* negative? */ + add (&unpacked, unpacked, one); /* truncate toward zero */ + pack (result, unpacked); /* (overflow cannot occur) */ + } return; } -#endif /* defined (HAVE_INT64) */ +#endif /* defined (HAVE_INT64) */ diff --git a/HP2100/hp2100_fp1.h b/HP2100/hp2100_fp1.h index 36de3335..539eaf60 100644 --- a/HP2100/hp2100_fp1.h +++ b/HP2100/hp2100_fp1.h @@ -25,17 +25,17 @@ */ #ifndef _HP2100_FP1_H_ -#define _HP2100_FP1_H_ 0 - +#define _HP2100_FP1_H_ 0 /* HP memory representation of an extended-precision number */ -typedef struct { uint32 high; - uint32 low; } XPN; +typedef struct { + uint32 high; + uint32 low; + } XPN; -#define AS_XPN(x) (*(XPN *) &(x)) /* view as XPN */ - +#define AS_XPN(x) (*(XPN *) &(x)) /* view as XPN */ XPN ReadX (uint32 va); void WriteX (uint32 va, XPN packed); diff --git a/HP2100/hp2100_ipl.c b/HP2100/hp2100_ipl.c index 6e7a271a..0a401b2c 100644 --- a/HP2100/hp2100_ipl.c +++ b/HP2100/hp2100_ipl.c @@ -1,6 +1,6 @@ /* hp2100_ipl.c: HP 2000 interprocessor link simulator - Copyright (c) 2002-2004, Robert M Supnik + Copyright (c) 2002-2005, 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"), @@ -19,43 +19,44 @@ 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 + 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 12566B interprocessor link pair + ipli, iplo 12566B interprocessor link pair - 07-Oct-04 JDB Fixed enable/disable from either device - 26-Apr-04 RMS Fixed SFS x,C and SFC x,C - Implemented DMA SRQ (follows FLG) - 21-Dec-03 RMS Adjusted ipl_ptime for TSB (from Mike Gemeny) - 09-May-03 RMS Added network device flag - 31-Jan-03 RMS Links are full duplex (found by Mike Gemeny) + 16-Aug-05 RMS Fixed C++ declaration and cast problems + 07-Oct-04 JDB Fixed enable/disable from either device + 26-Apr-04 RMS Fixed SFS x,C and SFC x,C + Implemented DMA SRQ (follows FLG) + 21-Dec-03 RMS Adjusted ipl_ptime for TSB (from Mike Gemeny) + 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 */ +#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], dev_srq[2]; extern FILE *sim_log; -int32 ipl_ptime = 31; /* polling interval */ -int32 ipl_stopioe = 0; /* stop on error */ -int32 ipl_hold[2] = { 0 }; /* holding character */ +int32 ipl_ptime = 31; /* 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); @@ -69,86 +70,93 @@ 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 + ipli_dev IPLI device descriptor + ipli_unit IPLI unit descriptor + ipli_reg IPLI register list */ DIB ipl_dib[] = { - { IPLI, 0, 0, 0, 0, 0, &ipliio }, - { IPLO, 0, 0, 0, 0, 0, &iploio } }; + { IPLI, 0, 0, 0, 0, 0, &ipliio }, + { IPLO, 0, 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) } }; + { 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) }, - { FLDATA (SRQ, ipli_dib.srq, 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 } }; + { 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) }, + { FLDATA (SRQ, ipli_dib.srq, 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 } }; + { 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 }; + "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 + 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) }, - { FLDATA (SRQ, iplo_dib.srq, 0) }, - { ORDATA (HOLD, ipl_hold[1], 8) }, - { DRDATA (TIME, ipl_ptime, 24), PV_LEFT }, - { ORDATA (DEVNO, iplo_dib.devno, 6), REG_HRO }, - { NULL } }; + { 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) }, + { FLDATA (SRQ, iplo_dib.srq, 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 */ + "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 + }; + +/* I/O instructions */ int32 ipliio (int32 inst, int32 IR, int32 dat) { @@ -166,58 +174,74 @@ uint32 u, dev, odev; int32 sta; char msg[2]; -dev = IR & I_DEVMASK; /* get device no */ -switch (inst) { /* case on opcode */ -case ioFLG: /* flag clear/set */ - if ((IR & I_HC) == 0) { setFSR (dev); } /* STF */ - break; -case ioSFC: /* skip flag clear */ - if (FLG (dev) == 0) PC = (PC + 1) & VAMASK; - break; -case ioSFS: /* skip flag set */ - if (FLG (dev) != 0) PC = (PC + 1) & VAMASK; - break; -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 */ - setFSR (odev); } /* set other flag */ - else return SCPE_UNATT; } /* lose */ - break; -default: - break; } -if (IR & I_HC) { clrFSR (dev); } /* H/C option */ +dev = IR & I_DEVMASK; /* get device no */ +switch (inst) { /* case on opcode */ + + case ioFLG: /* flag clear/set */ + if ((IR & I_HC) == 0) { setFSR (dev); } /* STF */ + break; + + case ioSFC: /* skip flag clear */ + if (FLG (dev) == 0) PC = (PC + 1) & VAMASK; + break; + + case ioSFS: /* skip flag set */ + if (FLG (dev) != 0) PC = (PC + 1) & VAMASK; + break; + + 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 */ + setFSR (odev); /* set other flag */ + } + else return SCPE_UNATT; /* lose */ + } + break; + + default: + break; + } + +if (IR & I_HC) { clrFSR (dev); } /* H/C option */ return dat; } - + /* Unit service - poll for input */ t_stat ipl_svc (UNIT *uptr) @@ -225,27 +249,31 @@ t_stat ipl_svc (UNIT *uptr) int32 u, nb, dev; char 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; } +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; } +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; } + 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 */ + (((int32) msg[1]) & 0377); +dev = ipl_dib[u].devno; /* get device number */ +clrCMD (dev); /* clr cmd, set flag */ setFSR (dev); return SCPE_OK; } @@ -254,16 +282,19 @@ 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 */ +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) @@ -271,13 +302,13 @@ t_stat ipl_reset (DEVICE *dptr) DIB *dibp = (DIB *) dptr->ctxt; UNIT *uptr = dptr->units; -hp_enbdis_pair (dptr, /* make pair cons */ - (dptr == &ipli_dev)? &iplo_dev: &ipli_dev); -dibp->cmd = dibp->ctl = 0; /* clear cmd, ctl */ -dibp->flg = dibp->fbf = dibp->srq = 1; /* set flg, fbf, srq */ -uptr->IBUF = uptr->OBUF = 0; /* clr buffers */ +hp_enbdis_pair (dptr, /* make pair cons */ + (dptr == &ipli_dev)? &iplo_dev: &ipli_dev); +dibp->cmd = dibp->ctl = 0; /* clear cmd, ctl */ +dibp->flg = dibp->fbf = dibp->srq = 1; /* set flg, fbf, srq */ +uptr->IBUF = uptr->OBUF = 0; /* clr buffers */ if (uptr->flags & UNIT_ATT) sim_activate (uptr, ipl_ptime); -else sim_cancel (uptr); /* deactivate unit */ +else sim_cancel (uptr); /* deactivate unit */ uptr->flags = uptr->flags & ~UNIT_HOLD; return SCPE_OK; } @@ -302,43 +333,49 @@ 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; } + 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"); } +tptr = (char *) 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; } @@ -346,17 +383,19 @@ return SCPE_OK; t_stat ipl_detach (UNIT *uptr) { -if (!(uptr->flags & UNIT_ATT)) return SCPE_OK; /* attached? */ +if (!(uptr->flags & UNIT_ATT)) 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 */ +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 */ +sim_cancel (uptr); /* don't poll */ return SCPE_OK; } @@ -378,87 +417,90 @@ return SCPE_OK; 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; } + 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 MAX_BASE 073 -#define IPL_PNTR 074 -#define PTR_PNTR 075 -#define IPL_DEVA 076 -#define PTR_DEVA 077 +#define MAX_BASE 073 +#define IPL_PNTR 074 +#define PTR_PNTR 075 +#define IPL_DEVA 076 +#define PTR_DEVA 077 static const uint32 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 */ -}; + 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) { @@ -468,12 +510,12 @@ extern UNIT cpu_unit; extern uint32 SR; extern uint16 *M; -devi = ipli_dib.devno; /* get device no */ +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 + MAX_BASE] = (~PC + 1) & DMASK; /* fix ups */ +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 + MAX_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; diff --git a/HP2100/hp2100_lps.c b/HP2100/hp2100_lps.c index 573eeb17..38b8e593 100644 --- a/HP2100/hp2100_lps.c +++ b/HP2100/hp2100_lps.c @@ -1,6 +1,6 @@ /* hp2100_lps.c: HP 2100 12653A line printer simulator - Copyright (c) 1993-2004, Robert M. Supnik + Copyright (c) 1993-2005, 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"), @@ -19,33 +19,33 @@ 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 + 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 12566B microcircuit interface) + lps 12653A 2767 line printer + (based on 12566B microcircuit interface) - 19-Nov-04 JDB Added restart when set online, etc. - Fixed col count for non-printing chars - 01-Oct-04 JDB Added SET OFFLINE/ONLINE, POWEROFF/POWERON - Fixed status returns for error conditions - Fixed handling of non-printing characters - Fixed handling of characters after column 80 - Improved timing model accuracy for RTE - Added fast/realistic timing - Added debug printouts - 03-Jun-04 RMS Fixed timing (found by Dave Bryan) - 26-Apr-04 RMS Fixed SFS x,C and SFC x,C - Implemented DMA SRQ (follows FLG) - 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 + 19-Nov-04 JDB Added restart when set online, etc. + Fixed col count for non-printing chars + 01-Oct-04 JDB Added SET OFFLINE/ONLINE, POWEROFF/POWERON + Fixed status returns for error conditions + Fixed handling of non-printing characters + Fixed handling of characters after column 80 + Improved timing model accuracy for RTE + Added fast/realistic timing + Added debug printouts + 03-Jun-04 RMS Fixed timing (found by Dave Bryan) + 26-Apr-04 RMS Fixed SFS x,C and SFC x,C + Implemented DMA SRQ (follows FLG) + 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 The 2767 impact printer has a rotating drum with 80 columns of 64 raised characters. ASCII codes 32 through 95 (SPACE through "_") form the print @@ -104,63 +104,65 @@ #include "hp2100_defs.h" -#define LPS_ZONECNT 20 /* zone char count */ -#define LPS_PAGECNT 80 /* page char count */ -#define LPS_PAGELNT 60 /* page line length */ -#define LPS_FORMLNT 66 /* form line length */ +#define LPS_ZONECNT 20 /* zone char count */ +#define LPS_PAGECNT 80 /* page char count */ +#define LPS_PAGELNT 60 /* page line length */ +#define LPS_FORMLNT 66 /* form line length */ /* Printer power states */ -#define LPS_ON 0 /* power is on */ -#define LPS_OFF 1 /* power is off */ -#define LPS_TURNING_ON 2 /* power is turning on */ +#define LPS_ON 0 /* power is on */ +#define LPS_OFF 1 /* power is off */ +#define LPS_TURNING_ON 2 /* power is turning on */ -#define LPS_BUSY 0000001 /* busy status */ -#define LPS_NRDY 0100000 /* not ready status */ -#define LPS_PWROFF LPS_BUSY | LPS_NRDY /* power-off status */ +#define LPS_BUSY 0000001 /* busy status */ +#define LPS_NRDY 0100000 /* not ready status */ +#define LPS_PWROFF LPS_BUSY | LPS_NRDY /* power-off status */ -#define UNIT_V_DIAG (UNIT_V_UF + 0) /* diagnostic mode */ -#define UNIT_V_POWEROFF (UNIT_V_UF + 1) /* unit powered off */ -#define UNIT_V_OFFLINE (UNIT_V_UF + 2) /* unit offline */ -#define UNIT_DIAG (1 << UNIT_V_DIAG) -#define UNIT_POWEROFF (1 << UNIT_V_POWEROFF) -#define UNIT_OFFLINE (1 << UNIT_V_OFFLINE) +#define UNIT_V_DIAG (UNIT_V_UF + 0) /* diagnostic mode */ +#define UNIT_V_POWEROFF (UNIT_V_UF + 1) /* unit powered off */ +#define UNIT_V_OFFLINE (UNIT_V_UF + 2) /* unit offline */ +#define UNIT_DIAG (1 << UNIT_V_DIAG) +#define UNIT_POWEROFF (1 << UNIT_V_POWEROFF) +#define UNIT_OFFLINE (1 << UNIT_V_OFFLINE) extern uint32 PC; extern uint32 dev_cmd[2], dev_ctl[2], dev_flg[2], dev_fbf[2], dev_srq[2]; extern FILE *sim_deb; -int32 lps_ccnt = 0; /* character count */ -int32 lps_lcnt = 0; /* line count */ -int32 lps_stopioe = 0; /* stop on error */ -int32 lps_sta = 0; /* printer status */ -int32 lps_timing = 1; /* timing type */ -uint32 lps_power = LPS_ON; /* power state */ +int32 lps_ccnt = 0; /* character count */ +int32 lps_lcnt = 0; /* line count */ +int32 lps_stopioe = 0; /* stop on error */ +int32 lps_sta = 0; /* printer status */ +int32 lps_timing = 1; /* timing type */ +uint32 lps_power = LPS_ON; /* power state */ /* Hardware timing: - (based on 1580 instr/msec) instr msec calc msec - ------------------------ + (based on 1580 instr/msec) instr msec calc msec + ------------------------ - character transfer time : ctime = 2 2 us - per-zone printing time : ptime = 55300 35 40 - per-line paper slew time : stime = 17380 11 13 - power-on ready delay time : rtime = 158000 100 NOTE: the printer acknowledges before the print motion has stopped to allow - for continuous slew, so the set times are a bit less than the calculated - operation time from the manual. + for continuous slew, so the set times are a bit less than the calculated + operation time from the manual. */ -int32 lps_ctime = 0; /* char xfer time */ -int32 lps_ptime = 0; /* zone printing time */ -int32 lps_stime = 0; /* paper slew time */ -int32 lps_rtime = 0; /* power-on ready time */ +int32 lps_ctime = 0; /* char xfer time */ +int32 lps_ptime = 0; /* zone printing time */ +int32 lps_stime = 0; /* paper slew time */ +int32 lps_rtime = 0; /* power-on ready time */ -typedef int32 TIMESET[4]; /* set of controller times */ +typedef int32 TIMESET[4]; /* set of controller times */ int32 *const lps_timers[] = { &lps_ctime, &lps_ptime, &lps_stime, &lps_rtime }; -const TIMESET lps_times[2] = { { 2, 55300, 17380, 158000 }, /* REALTIME */ - { 2, 1000, 1000, 1000 } }; /* FASTTIME */ +const TIMESET lps_times[2] = { + { 2, 55300, 17380, 158000 }, /* REALTIME */ + { 2, 1000, 1000, 1000 } /* FASTTIME */ + }; DEVICE lps_dev; int32 lpsio (int32 inst, int32 IR, int32 dat); @@ -175,189 +177,219 @@ t_stat lps_show_timing (FILE *st, UNIT *uptr, int32 val, void *desc); /* LPS data structures - lps_dev LPS device descriptor - lps_unit LPS unit descriptor - lps_reg LPS register list + lps_dev LPS device descriptor + lps_unit LPS unit descriptor + lps_reg LPS register list */ DIB lps_dib = { LPS, 0, 0, 0, 0, 0, &lpsio }; UNIT lps_unit = { - UDATA (&lps_svc, UNIT_SEQ+UNIT_ATTABLE+UNIT_DISABLE, 0) }; + UDATA (&lps_svc, UNIT_SEQ+UNIT_ATTABLE+UNIT_DISABLE, 0) + }; REG lps_reg[] = { - { ORDATA (BUF, lps_unit.buf, 16) }, - { ORDATA (STA, lps_sta, 16) }, - { ORDATA (POWER, lps_power, 2), REG_RO }, - { FLDATA (CMD, lps_dib.cmd, 0) }, - { FLDATA (CTL, lps_dib.ctl, 0) }, - { FLDATA (FLG, lps_dib.flg, 0) }, - { FLDATA (FBF, lps_dib.fbf, 0) }, - { FLDATA (SRQ, lps_dib.srq, 0) }, - { DRDATA (CCNT, lps_ccnt, 7), PV_LEFT }, - { DRDATA (LCNT, lps_lcnt, 7), PV_LEFT }, - { DRDATA (POS, lps_unit.pos, T_ADDR_W), PV_LEFT }, - { DRDATA (CTIME, lps_ctime, 24), PV_LEFT }, - { DRDATA (PTIME, lps_ptime, 24), PV_LEFT }, - { DRDATA (STIME, lps_stime, 24), PV_LEFT }, - { DRDATA (RTIME, lps_rtime, 24), PV_LEFT }, - { FLDATA (TIMING, lps_timing, 0), REG_HRO }, - { FLDATA (STOP_IOE, lps_stopioe, 0) }, - { ORDATA (DEVNO, lps_dib.devno, 6), REG_HRO }, - { NULL } }; + { ORDATA (BUF, lps_unit.buf, 16) }, + { ORDATA (STA, lps_sta, 16) }, + { ORDATA (POWER, lps_power, 2), REG_RO }, + { FLDATA (CMD, lps_dib.cmd, 0) }, + { FLDATA (CTL, lps_dib.ctl, 0) }, + { FLDATA (FLG, lps_dib.flg, 0) }, + { FLDATA (FBF, lps_dib.fbf, 0) }, + { FLDATA (SRQ, lps_dib.srq, 0) }, + { DRDATA (CCNT, lps_ccnt, 7), PV_LEFT }, + { DRDATA (LCNT, lps_lcnt, 7), PV_LEFT }, + { DRDATA (POS, lps_unit.pos, T_ADDR_W), PV_LEFT }, + { DRDATA (CTIME, lps_ctime, 24), PV_LEFT }, + { DRDATA (PTIME, lps_ptime, 24), PV_LEFT }, + { DRDATA (STIME, lps_stime, 24), PV_LEFT }, + { DRDATA (RTIME, lps_rtime, 24), PV_LEFT }, + { FLDATA (TIMING, lps_timing, 0), REG_HRO }, + { 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 }, - { UNIT_POWEROFF, UNIT_POWEROFF, "power off", "POWEROFF", lps_poweroff }, - { UNIT_POWEROFF, 0, "power on", "POWERON", lps_poweron }, - { UNIT_OFFLINE, UNIT_OFFLINE, "offline", "OFFLINE", NULL }, - { UNIT_OFFLINE, 0, "online", "ONLINE", lps_restart }, - { MTAB_XTD | MTAB_VDV, 0, NULL, "REALTIME", - &lps_set_timing, NULL, NULL }, - { MTAB_XTD | MTAB_VDV, 1, NULL, "FASTTIME", - &lps_set_timing, NULL, NULL }, - { MTAB_XTD | MTAB_VDV, 0, "TIMING", NULL, - NULL, &lps_show_timing, NULL }, - { MTAB_XTD | MTAB_VDV, 0, "DEVNO", "DEVNO", - &hp_setdev, &hp_showdev, &lps_dev }, - { 0 } }; + { UNIT_DIAG, UNIT_DIAG, "diagnostic mode", "DIAG", NULL }, + { UNIT_DIAG, 0, "printer mode", "PRINTER", NULL }, + { UNIT_POWEROFF, UNIT_POWEROFF, "power off", "POWEROFF", lps_poweroff }, + { UNIT_POWEROFF, 0, "power on", "POWERON", lps_poweron }, + { UNIT_OFFLINE, UNIT_OFFLINE, "offline", "OFFLINE", NULL }, + { UNIT_OFFLINE, 0, "online", "ONLINE", lps_restart }, + { MTAB_XTD | MTAB_VDV, 0, NULL, "REALTIME", + &lps_set_timing, NULL, NULL }, + { MTAB_XTD | MTAB_VDV, 1, NULL, "FASTTIME", + &lps_set_timing, NULL, NULL }, + { MTAB_XTD | MTAB_VDV, 0, "TIMING", NULL, + NULL, &lps_show_timing, 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, &lps_attach, NULL, - &lps_dib, DEV_DISABLE | DEV_DIS | DEV_DEBUG }; - -/* Line printer IOT routine */ + "LPS", &lps_unit, lps_reg, lps_mod, + 1, 10, 31, 1, 8, 8, + NULL, NULL, &lps_reset, + NULL, &lps_attach, NULL, + &lps_dib, DEV_DISABLE | DEV_DIS | DEV_DEBUG + }; + +/* IO instructions */ int32 lpsio (int32 inst, int32 IR, int32 dat) { int32 dev, sched; -dev = IR & I_DEVMASK; /* get device no */ -switch (inst) { /* case on opcode */ -case ioFLG: /* flag clear/set */ - if ((IR & I_HC) == 0) { setFSR (dev); } /* STF */ - break; -case ioSFC: /* skip flag clear */ - if (FLG (dev) == 0) PC = (PC + 1) & VAMASK; - break; -case ioSFS: /* skip flag set */ - if (FLG (dev) != 0) PC = (PC + 1) & VAMASK; - break; -case ioOTX: /* output */ - if (DEBUG_PRS (lps_dev)) - fprintf (sim_deb, ">>LPS OTx: Character %06o output\n", dat); - 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? */ - if (lps_power == LPS_ON) /* power on? */ - if (((lps_unit.flags & UNIT_ATT) == 0) || /* paper out? */ - (lps_unit.flags & UNIT_OFFLINE) || /* offline? */ - sim_is_active (&lps_unit)) lps_sta = LPS_BUSY; - else lps_sta = 0; - else lps_sta = LPS_PWROFF; - dat = dat | lps_sta; /* diag, rtn status */ - if (DEBUG_PRS (lps_dev)) - fprintf (sim_deb, ">>LPS LIx: Status %06o returned\n", dat); - 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 { /* real lpt, sched */ - if (DEBUG_PRS (lps_dev)) fprintf (sim_deb, - ">>LPS STC: Character %06o scheduled for line %d, column %d, ", - lps_unit.buf, lps_lcnt + 1, lps_ccnt + 1); - if ((lps_unit.buf != '\f') && - (lps_unit.buf != '\n') && - (lps_unit.buf != '\r')) { /* normal char */ - lps_ccnt = lps_ccnt + 1; /* incr char counter */ - if (lps_ccnt % LPS_ZONECNT == 0) /* end of zone? */ - sched = lps_ptime; /* print zone */ - else sched = lps_ctime; } /* xfer char */ - else { /* print cmd */ - if (lps_ccnt % LPS_ZONECNT == 0) /* last zone printed? */ - sched = lps_ctime; /* yes, so just char time */ - else sched = lps_ptime; /* no, so print needed */ - lps_ccnt = 0; /* reset char counter */ - if (lps_unit.buf == '\n') { /* line advance */ - lps_lcnt = (lps_lcnt + 1) % LPS_PAGELNT; - if (lps_lcnt > 0) sched = sched + lps_stime; - else sched = sched + /* allow for perf skip */ - lps_stime * (LPS_FORMLNT - LPS_PAGELNT); } - else if (lps_unit.buf == '\f') { /* form advance */ - sched = sched + lps_stime * (LPS_FORMLNT - lps_lcnt); - lps_lcnt = 0; } } - sim_activate (&lps_unit, sched); - if (DEBUG_PRS (lps_dev)) - fprintf (sim_deb, "time = %d\n", sched); } } - break; -default: - break; } -if (IR & I_HC) { clrFSR (dev); } /* H/C option */ +dev = IR & I_DEVMASK; /* get device no */ +switch (inst) { /* case on opcode */ + + case ioFLG: /* flag clear/set */ + if ((IR & I_HC) == 0) { setFSR (dev); } /* STF */ + break; + + case ioSFC: /* skip flag clear */ + if (FLG (dev) == 0) PC = (PC + 1) & VAMASK; + break; + + case ioSFS: /* skip flag set */ + if (FLG (dev) != 0) PC = (PC + 1) & VAMASK; + break; + + case ioOTX: /* output */ + if (DEBUG_PRS (lps_dev)) + fprintf (sim_deb, ">>LPS OTx: Character %06o output\n", dat); + 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? */ + if (lps_power == LPS_ON) { /* power on? */ + if (((lps_unit.flags & UNIT_ATT) == 0) || /* paper out? */ + (lps_unit.flags & UNIT_OFFLINE) || /* offline? */ + sim_is_active (&lps_unit)) lps_sta = LPS_BUSY; + else lps_sta = 0; + } + else lps_sta = LPS_PWROFF; + } + dat = dat | lps_sta; /* diag, rtn status */ + if (DEBUG_PRS (lps_dev)) + fprintf (sim_deb, ">>LPS LIx: Status %06o returned\n", dat); + 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 { /* real lpt, sched */ + if (DEBUG_PRS (lps_dev)) fprintf (sim_deb, + ">>LPS STC: Character %06o scheduled for line %d, column %d, ", + lps_unit.buf, lps_lcnt + 1, lps_ccnt + 1); + if ((lps_unit.buf != '\f') && + (lps_unit.buf != '\n') && + (lps_unit.buf != '\r')) { /* normal char */ + lps_ccnt = lps_ccnt + 1; /* incr char counter */ + if (lps_ccnt % LPS_ZONECNT == 0) /* end of zone? */ + sched = lps_ptime; /* print zone */ + else sched = lps_ctime; /* xfer char */ + } + else { /* print cmd */ + if (lps_ccnt % LPS_ZONECNT == 0) /* last zone printed? */ + sched = lps_ctime; /* yes, so just char time */ + else sched = lps_ptime; /* no, so print needed */ + lps_ccnt = 0; /* reset char counter */ + if (lps_unit.buf == '\n') { /* line advance */ + lps_lcnt = (lps_lcnt + 1) % LPS_PAGELNT; + if (lps_lcnt > 0) sched = sched + lps_stime; + else sched = sched + /* allow for perf skip */ + lps_stime * (LPS_FORMLNT - LPS_PAGELNT); + } + else if (lps_unit.buf == '\f') { /* form advance */ + sched = sched + lps_stime * (LPS_FORMLNT - lps_lcnt); + lps_lcnt = 0; + } + } + sim_activate (&lps_unit, sched); + if (DEBUG_PRS (lps_dev)) + fprintf (sim_deb, "time = %d\n", sched); + } + } + break; + + default: + break; + } + +if (IR & I_HC) { clrFSR (dev); } /* H/C option */ return dat; } +/* Unit service */ + t_stat lps_svc (UNIT *uptr) { int32 dev; int32 c = uptr->buf & 0177; -if (lps_power == LPS_TURNING_ON) { /* printer warmed up? */ - lps_power = LPS_ON; /* change state */ - lps_restart (uptr, 0, NULL, NULL); /* restart I/O if hung */ - if (DEBUG_PRS (lps_dev)) - fputs (">>LPS svc: Power state is ON\n", sim_deb); - return SCPE_OK; } /* done */ -dev = lps_dib.devno; /* get dev no */ -if (uptr->flags & UNIT_DIAG) { /* diagnostic? */ - lps_sta = uptr->buf; /* loop back */ - clrCMD (dev); /* clear cmd */ - setFSR (dev); /* set flag, fbf */ - return SCPE_OK; } /* done */ -if ((uptr->flags & UNIT_ATT) == 0) /* attached? */ - return IORETURN (lps_stopioe, SCPE_UNATT); -else if (uptr->flags & UNIT_OFFLINE) /* offline? */ - return IORETURN (lps_stopioe, STOP_OFFLINE); -else if (uptr->flags & UNIT_POWEROFF) /* powered off? */ - return IORETURN (lps_stopioe, STOP_PWROFF); -clrCMD (dev); /* clear cmd */ -setFSR (dev); /* set flag, fbf */ -if (((c < ' ') || (c > '_')) && /* non-printing char? */ +if (lps_power == LPS_TURNING_ON) { /* printer warmed up? */ + lps_power = LPS_ON; /* change state */ + lps_restart (uptr, 0, NULL, NULL); /* restart I/O if hung */ + if (DEBUG_PRS (lps_dev)) + fputs (">>LPS svc: Power state is ON\n", sim_deb); + return SCPE_OK; /* done */ + } +dev = lps_dib.devno; /* get dev no */ +if (uptr->flags & UNIT_DIAG) { /* diagnostic? */ + lps_sta = uptr->buf; /* loop back */ + clrCMD (dev); /* clear cmd */ + setFSR (dev); /* set flag, fbf */ + return SCPE_OK; /* done */ + } +if ((uptr->flags & UNIT_ATT) == 0) /* attached? */ + return IORETURN (lps_stopioe, SCPE_UNATT); +else if (uptr->flags & UNIT_OFFLINE) /* offline? */ + return IORETURN (lps_stopioe, STOP_OFFLINE); +else if (uptr->flags & UNIT_POWEROFF) /* powered off? */ + return IORETURN (lps_stopioe, STOP_PWROFF); +clrCMD (dev); /* clear cmd */ +setFSR (dev); /* set flag, fbf */ +if (((c < ' ') || (c > '_')) && /* non-printing char? */ (c != '\f') && (c != '\n') && (c != '\r')) { - if (DEBUG_PRS (lps_dev)) - fprintf (sim_deb, ">>LPS svc: Character %06o erased\n", c); - c = ' '; } /* replace with blank */ -if (lps_ccnt > LPS_PAGECNT) { /* 81st character? */ - fputc ('\r', uptr->fileref); /* return to line start */ - uptr->pos = uptr->pos + 1; /* update pos */ - lps_ccnt = 1; /* reset char counter */ - if (DEBUG_PRS (lps_dev)) - fputs (">>LPS svc: Line wraparound to column 1\n", sim_deb); } -fputc (c, uptr->fileref); /* "print" char */ -uptr->pos = uptr->pos + 1; /* update pos */ + if (DEBUG_PRS (lps_dev)) + fprintf (sim_deb, ">>LPS svc: Character %06o erased\n", c); + c = ' '; /* replace with blank */ + } +if (lps_ccnt > LPS_PAGECNT) { /* 81st character? */ + fputc ('\r', uptr->fileref); /* return to line start */ + uptr->pos = uptr->pos + 1; /* update pos */ + lps_ccnt = 1; /* reset char counter */ + if (DEBUG_PRS (lps_dev)) + fputs (">>LPS svc: Line wraparound to column 1\n", sim_deb); + } +fputc (c, uptr->fileref); /* "print" char */ +uptr->pos = uptr->pos + 1; /* update pos */ if (DEBUG_PRS (lps_dev)) - fprintf (sim_deb, ">>LPS svc: Character %06o printed\n", c); -if ((lps_lcnt == 0) && (c == '\n')) { /* LF did TOF? */ - fputc ('\f', uptr->fileref); /* do perf skip */ - uptr->pos = uptr->pos + 1; /* update pos */ - if (DEBUG_PRS (lps_dev)) - fputs (">>LPS svc: Perforation skip to TOF\n", sim_deb); } + fprintf (sim_deb, ">>LPS svc: Character %06o printed\n", c); +if ((lps_lcnt == 0) && (c == '\n')) { /* LF did TOF? */ + fputc ('\f', uptr->fileref); /* do perf skip */ + uptr->pos = uptr->pos + 1; /* update pos */ + if (DEBUG_PRS (lps_dev)) + fputs (">>LPS svc: Perforation skip to TOF\n", sim_deb); + } if (ferror (uptr->fileref)) { - perror ("LPS I/O error"); - clearerr (uptr->fileref); - return SCPE_IOERR; } + perror ("LPS I/O error"); + clearerr (uptr->fileref); + return SCPE_IOERR; + } return SCPE_OK; } @@ -365,12 +397,12 @@ return SCPE_OK; t_stat lps_reset (DEVICE *dptr) { -lps_dib.cmd = lps_dib.ctl = 0; /* clear cmd, ctl */ -lps_dib.flg = lps_dib.fbf = lps_dib.srq = 1; /* set flg, fbf, srq */ +lps_dib.cmd = lps_dib.ctl = 0; /* clear cmd, ctl */ +lps_dib.flg = lps_dib.fbf = lps_dib.srq = 1; /* set flg, fbf, srq */ lps_sta = lps_unit.buf = 0; -lps_power = LPS_ON; /* power is on */ -sim_cancel (&lps_unit); /* deactivate unit */ -lps_set_timing (NULL, lps_timing, NULL, NULL); /* init timing set */ +lps_power = LPS_ON; /* power is on */ +sim_cancel (&lps_unit); /* deactivate unit */ +lps_set_timing (NULL, lps_timing, NULL, NULL); /* init timing set */ return SCPE_OK; } @@ -391,7 +423,7 @@ return SCPE_OK; t_stat lps_restart (UNIT *uptr, int32 value, char *cptr, void *desc) { if (lps_dib.cmd && lps_dib.ctl && !sim_is_active (uptr)) - sim_activate (uptr, 0); /* reschedule I/O */ + sim_activate (uptr, 0); /* reschedule I/O */ return SCPE_OK; } @@ -399,7 +431,7 @@ return SCPE_OK; t_stat lps_poweroff (UNIT *uptr, int32 value, char *cptr, void *desc) { -lps_power = LPS_OFF; /* change state */ +lps_power = LPS_OFF; /* change state */ if (DEBUG_PRS (lps_dev)) fputs (">>LPS set: Power state is OFF\n", sim_deb); return SCPE_OK; } @@ -408,17 +440,19 @@ return SCPE_OK; t_stat lps_poweron (UNIT *uptr, int32 value, char *cptr, void *desc) { -if (lps_unit.flags & UNIT_DIAG) { /* diag mode? */ - lps_power = LPS_ON; /* no delay */ - if (DEBUG_PRS (lps_dev)) - fputs (">>LPS set: Power state is ON\n", sim_deb); } +if (lps_unit.flags & UNIT_DIAG) { /* diag mode? */ + lps_power = LPS_ON; /* no delay */ + if (DEBUG_PRS (lps_dev)) + fputs (">>LPS set: Power state is ON\n", sim_deb); + } else { - lps_power = LPS_TURNING_ON; /* change state */ - lps_unit.flags |= UNIT_OFFLINE; /* set offline */ - sim_activate (&lps_unit, lps_rtime); /* schedule ready */ - if (DEBUG_PRS (lps_dev)) fprintf (sim_deb, - ">>LPS set: Power state is TURNING ON, scheduled time = %d\n", - lps_rtime ); } + lps_power = LPS_TURNING_ON; /* change state */ + lps_unit.flags |= UNIT_OFFLINE; /* set offline */ + sim_activate (&lps_unit, lps_rtime); /* schedule ready */ + if (DEBUG_PRS (lps_dev)) fprintf (sim_deb, + ">>LPS set: Power state is TURNING ON, scheduled time = %d\n", + lps_rtime ); + } return SCPE_OK; } @@ -426,8 +460,8 @@ return SCPE_OK; t_stat lps_attach (UNIT *uptr, char *cptr) { -lps_ccnt = lps_lcnt = 0; /* top of form */ -lps_restart (uptr, 0, NULL, NULL); /* restart I/O if hung */ +lps_ccnt = lps_lcnt = 0; /* top of form */ +lps_restart (uptr, 0, NULL, NULL); /* restart I/O if hung */ return attach_unit (uptr, cptr); } @@ -437,9 +471,9 @@ t_stat lps_set_timing (UNIT *uptr, int32 val, char *cptr, void *desc) { int32 i; -lps_timing = (val != 0); /* determine choice */ +lps_timing = (val != 0); /* determine choice */ for (i = 0; i < (sizeof (lps_timers) / sizeof (lps_timers[0])); i++) - *lps_timers[i] = lps_times[lps_timing][i]; /* assign times */ + *lps_timers[i] = lps_times[lps_timing][i]; /* assign times */ return SCPE_OK; } diff --git a/HP2100/hp2100_lpt.c b/HP2100/hp2100_lpt.c index 3363a610..4d24226c 100644 --- a/HP2100/hp2100_lpt.c +++ b/HP2100/hp2100_lpt.c @@ -1,6 +1,6 @@ /* hp2100_lpt.c: HP 2100 12845B line printer simulator - Copyright (c) 1993-2004, Robert M. Supnik + Copyright (c) 1993-2005, 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"), @@ -19,21 +19,21 @@ 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 + 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 12845B 2607 line printer + lpt 12845B 2607 line printer - 19-Nov-04 JDB Added restart when set online, etc. - 29-Sep-04 JDB Added SET OFFLINE/ONLINE, POWEROFF/POWERON - Fixed status returns for error conditions - Fixed TOF handling so form remains on line 0 - 03-Jun-04 RMS Fixed timing (found by Dave Bryan) - 26-Apr-04 RMS Fixed SFS x,C and SFC x,C - Implemented DMA SRQ (follows FLG) - 25-Apr-03 RMS Revised for extended file support - 24-Oct-02 RMS Cloned from 12653A + 19-Nov-04 JDB Added restart when set online, etc. + 29-Sep-04 JDB Added SET OFFLINE/ONLINE, POWEROFF/POWERON + Fixed status returns for error conditions + Fixed TOF handling so form remains on line 0 + 03-Jun-04 RMS Fixed timing (found by Dave Bryan) + 26-Apr-04 RMS Fixed SFS x,C and SFC x,C + Implemented DMA SRQ (follows FLG) + 25-Apr-03 RMS Revised for extended file support + 24-Oct-02 RMS Cloned from 12653A The 2607 provides three status bits via the interface: @@ -67,32 +67,33 @@ #include "hp2100_defs.h" -#define LPT_PAGELNT 60 /* page length */ +#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_PWROFF LPT_RDY | LPT_PAPO | LPT_NBSY /* power-off status */ +#define LPT_NBSY 0000001 /* not busy */ +#define LPT_PAPO 0040000 /* paper out */ +#define LPT_RDY 0100000 /* ready */ +#define LPT_PWROFF LPT_RDY | LPT_PAPO | LPT_NBSY /* power-off status */ -#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 */ +#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 */ -#define UNIT_V_POWEROFF (UNIT_V_UF + 0) /* unit powered off */ -#define UNIT_V_OFFLINE (UNIT_V_UF + 1) /* unit offline */ -#define UNIT_POWEROFF (1 << UNIT_V_POWEROFF) -#define UNIT_OFFLINE (1 << UNIT_V_OFFLINE) +#define UNIT_V_POWEROFF (UNIT_V_UF + 0) /* unit powered off */ +#define UNIT_V_OFFLINE (UNIT_V_UF + 1) /* unit offline */ +#define UNIT_POWEROFF (1 << UNIT_V_POWEROFF) +#define UNIT_OFFLINE (1 << UNIT_V_OFFLINE) extern uint32 PC; extern uint32 dev_cmd[2], dev_ctl[2], dev_flg[2], dev_fbf[2], dev_srq[2]; -int32 lpt_ctime = 4; /* char time */ -int32 lpt_ptime = 10000; /* print time */ -int32 lpt_stopioe = 0; /* stop on error */ -int32 lpt_lcnt = 0; /* line count */ +int32 lpt_ctime = 4; /* char time */ +int32 lpt_ptime = 10000; /* print 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 }; + 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); @@ -103,132 +104,153 @@ 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 + lpt_dev LPT device descriptor + lpt_unit LPT unit descriptor + lpt_reg LPT register list */ DIB lpt_dib = { LPT, 0, 0, 0, 0, 0, &lptio }; UNIT lpt_unit = { - UDATA (&lpt_svc, UNIT_SEQ+UNIT_ATTABLE+UNIT_DISABLE, 0) }; + UDATA (&lpt_svc, UNIT_SEQ+UNIT_ATTABLE+UNIT_DISABLE, 0) + }; 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) }, - { FLDATA (SRQ, lpt_dib.srq, 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_ptime, 24), PV_LEFT }, - { FLDATA (STOP_IOE, lpt_stopioe, 0) }, - { ORDATA (DEVNO, lpt_dib.devno, 6), REG_HRO }, - { NULL } }; + { 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) }, + { FLDATA (SRQ, lpt_dib.srq, 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_ptime, 24), PV_LEFT }, + { FLDATA (STOP_IOE, lpt_stopioe, 0) }, + { ORDATA (DEVNO, lpt_dib.devno, 6), REG_HRO }, + { NULL } + }; MTAB lpt_mod[] = { - { UNIT_POWEROFF, UNIT_POWEROFF, "power off", "POWEROFF", NULL }, - { UNIT_POWEROFF, 0, "power on", "POWERON", lpt_restart }, - { UNIT_OFFLINE, UNIT_OFFLINE, "offline", "OFFLINE", NULL }, - { UNIT_OFFLINE, 0, "online", "ONLINE", lpt_restart }, - { MTAB_XTD | MTAB_VDV, 0, "DEVNO", "DEVNO", - &hp_setdev, &hp_showdev, &lpt_dev }, - { 0 } }; + { UNIT_POWEROFF, UNIT_POWEROFF, "power off", "POWEROFF", NULL }, + { UNIT_POWEROFF, 0, "power on", "POWERON", lpt_restart }, + { UNIT_OFFLINE, UNIT_OFFLINE, "offline", "OFFLINE", NULL }, + { UNIT_OFFLINE, 0, "online", "ONLINE", lpt_restart }, + { 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 */ + "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 + }; + +/* IO instructions */ 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) { setFSR (dev); } /* STF */ - break; -case ioSFC: /* skip flag clear */ - if (FLG (dev) == 0) PC = (PC + 1) & VAMASK; - break; -case ioSFS: /* skip flag set */ - if (FLG (dev) != 0) PC = (PC + 1) & VAMASK; - break; -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_POWEROFF) /* power off? */ - dat = dat | LPT_PWROFF; - else if (!(lpt_unit.flags & UNIT_OFFLINE)) /* online? */ - if (lpt_unit.flags & UNIT_ATT) { /* paper loaded? */ - dat = dat | LPT_RDY; - if (!sim_is_active (&lpt_unit)) /* printer busy? */ - dat = dat | LPT_NBSY; } - else if (lpt_lcnt == LPT_PAGELNT - 1) /* paper out, at BOF? */ - 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_ptime: lpt_ctime); } - break; -default: - break; } -if (IR & I_HC) { clrFSR (dev); } /* H/C option */ +dev = IR & I_DEVMASK; /* get device no */ +switch (inst) { /* case on opcode */ + + case ioFLG: /* flag clear/set */ + if ((IR & I_HC) == 0) { setFSR (dev); } /* STF */ + break; + + case ioSFC: /* skip flag clear */ + if (FLG (dev) == 0) PC = (PC + 1) & VAMASK; + break; + + case ioSFS: /* skip flag set */ + if (FLG (dev) != 0) PC = (PC + 1) & VAMASK; + break; + + 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_POWEROFF) /* power off? */ + dat = dat | LPT_PWROFF; + else if (!(lpt_unit.flags & UNIT_OFFLINE)) { /* online? */ + if (lpt_unit.flags & UNIT_ATT) { /* paper loaded? */ + dat = dat | LPT_RDY; + if (!sim_is_active (&lpt_unit)) /* printer busy? */ + dat = dat | LPT_NBSY; + } + else if (lpt_lcnt == LPT_PAGELNT - 1) /* paper out, at BOF? */ + 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_ptime: lpt_ctime); + } + break; + + default: + break; + } + +if (IR & I_HC) { clrFSR (dev); } /* H/C option */ return dat; } +/* Unit service */ + t_stat lpt_svc (UNIT *uptr) { int32 i, skip, chan, dev; -dev = lpt_dib.devno; /* get dev no */ -if ((uptr->flags & UNIT_ATT) == 0) /* attached? */ - return IORETURN (lpt_stopioe, SCPE_UNATT); -else if (uptr->flags & UNIT_OFFLINE) /* offline? */ - return IORETURN (lpt_stopioe, STOP_OFFLINE); -else if (uptr->flags & UNIT_POWEROFF) /* powered off? */ - return IORETURN (lpt_stopioe, STOP_PWROFF); -clrCMD (dev); /* clear cmd */ -setFSR (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 = 0; } - 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 */ +dev = lpt_dib.devno; /* get dev no */ +if ((uptr->flags & UNIT_ATT) == 0) /* attached? */ + return IORETURN (lpt_stopioe, SCPE_UNATT); +else if (uptr->flags & UNIT_OFFLINE) /* offline? */ + return IORETURN (lpt_stopioe, STOP_OFFLINE); +else if (uptr->flags & UNIT_POWEROFF) /* powered off? */ + return IORETURN (lpt_stopioe, STOP_PWROFF); +clrCMD (dev); /* clear cmd */ +setFSR (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 = 0; + } + 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 */ + perror ("LPT I/O error"); + clearerr (uptr->fileref); + return SCPE_IOERR; + } +lpt_unit.pos = ftell (uptr->fileref); /* update pos */ return SCPE_OK; } @@ -236,10 +258,10 @@ return SCPE_OK; t_stat lpt_reset (DEVICE *dptr) { -lpt_dib.cmd = lpt_dib.ctl = 0; /* clear cmd, ctl */ -lpt_dib.flg = lpt_dib.fbf = lpt_dib.srq = 1; /* set flg, fbf, srq */ +lpt_dib.cmd = lpt_dib.ctl = 0; /* clear cmd, ctl */ +lpt_dib.flg = lpt_dib.fbf = lpt_dib.srq = 1; /* set flg, fbf, srq */ lpt_unit.buf = 0; -sim_cancel (&lpt_unit); /* deactivate unit */ +sim_cancel (&lpt_unit); /* deactivate unit */ return SCPE_OK; } @@ -260,7 +282,7 @@ return SCPE_OK; t_stat lpt_restart (UNIT *uptr, int32 value, char *cptr, void *desc) { if (lpt_dib.cmd && lpt_dib.ctl && !sim_is_active (uptr)) - sim_activate (uptr, 0); /* reschedule I/O */ + sim_activate (uptr, 0); /* reschedule I/O */ return SCPE_OK; } @@ -268,7 +290,7 @@ return SCPE_OK; t_stat lpt_attach (UNIT *uptr, char *cptr) { -lpt_lcnt = 0; /* top of form */ -lpt_restart (uptr, 0, NULL, NULL); /* restart I/O if hung */ +lpt_lcnt = 0; /* top of form */ +lpt_restart (uptr, 0, NULL, NULL); /* restart I/O if hung */ return attach_unit (uptr, cptr); } diff --git a/HP2100/hp2100_ms.c b/HP2100/hp2100_ms.c index 032ee9a4..540ce04f 100644 --- a/HP2100/hp2100_ms.c +++ b/HP2100/hp2100_ms.c @@ -1,6 +1,6 @@ /* hp2100_ms.c: HP 2100 13181A/13183A magnetic tape simulator - Copyright (c) 1993-2004, Robert M. Supnik + Copyright (c) 1993-2005, 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"), @@ -19,49 +19,50 @@ 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 + 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 + ms 13181A 7970B 800bpi nine track magnetic tape + 13183A 7970E 1600bpi nine track magnetic tape - 01-Mar-05 JDB Added SET OFFLINE; rewind/offline now does not detach - 07-Oct-04 JDB Fixed enable/disable from either device - 14-Aug-04 JDB Fixed many functional and timing problems (from Dave Bryan) - - fixed erroneous execution of rejected command - - fixed erroneous execution of select-only command - - fixed erroneous execution of clear command - - fixed odd byte handling for read - - fixed spurious odd byte status on 13183A EOF - - modified handling of end of medium - - added detailed timing, with fast and realistic modes - - added reel sizes to simulate end of tape - - added debug printouts - 06-Jul-04 RMS Fixed spurious timing error after CLC (found by Dave Bryan) - 26-Apr-04 RMS Fixed SFS x,C and SFC x,C - Fixed SR setting in IBL - Revised IBL loader - Implemented DMA SRQ (follows FLG) - 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 + 22-Jul-05 RMS Fixed compiler warning on Solaris (from Doug Glyn) + 01-Mar-05 JDB Added SET OFFLINE; rewind/offline now does not detach + 07-Oct-04 JDB Fixed enable/disable from either device + 14-Aug-04 JDB Fixed many functional and timing problems (from Dave Bryan) + - fixed erroneous execution of rejected command + - fixed erroneous execution of select-only command + - fixed erroneous execution of clear command + - fixed odd byte handling for read + - fixed spurious odd byte status on 13183A EOF + - modified handling of end of medium + - added detailed timing, with fast and realistic modes + - added reel sizes to simulate end of tape + - added debug printouts + 06-Jul-04 RMS Fixed spurious timing error after CLC (found by Dave Bryan) + 26-Apr-04 RMS Fixed SFS x,C and SFC x,C + Fixed SR setting in IBL + Revised IBL loader + Implemented DMA SRQ (follows FLG) + 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 + 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. @@ -76,83 +77,83 @@ #include "hp2100_defs.h" #include "sim_tape.h" -#define UNIT_V_OFFLINE (MTUF_V_UF + 0) /* unit offline */ -#define UNIT_OFFLINE (1 << UNIT_V_OFFLINE) +#define UNIT_V_OFFLINE (MTUF_V_UF + 0) /* unit offline */ +#define UNIT_OFFLINE (1 << UNIT_V_OFFLINE) -#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 */ -#define REEL u5 /* tape reel size */ +#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 */ +#define REEL u5 /* tape reel size */ -#define TCAP (300 * 12 * 800) /* 300 ft capacity at 800bpi */ +#define TCAP (300 * 12 * 800) /* 300 ft capacity at 800bpi */ /* 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_CMPL 00400 /* completion state */ -#define FNC_V_SEL 9 /* select */ -#define FNC_M_SEL 017 -#define FNC_GETSEL(x) (((x) >> FNC_V_SEL) & FNC_M_SEL) +#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_CMPL 00400 /* completion state */ +#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 */ +#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 */ #define FNC_SEL ((FNC_M_SEL << FNC_V_SEL) | FNF_CHS) /* 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 (d) */ -#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) - +#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 (d) */ +#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 uint32 PC, SR; extern uint32 dev_cmd[2], dev_ctl[2], dev_flg[2], dev_fbf[2], dev_srq[2]; extern int32 sim_switches; extern UNIT cpu_unit; extern FILE *sim_deb; -int32 ms_ctype = 0; /* ctrl type */ -int32 ms_timing = 1; /* timing type */ -int32 msc_sta = 0; /* status */ -int32 msc_buf = 0; /* buffer */ -int32 msc_usl = 0; /* unit select */ +int32 ms_ctype = 0; /* ctrl type */ +int32 ms_timing = 1; /* timing type */ +int32 msc_sta = 0; /* status */ +int32 msc_buf = 0; /* buffer */ +int32 msc_usl = 0; /* unit select */ int32 msc_1st = 0; -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 */ +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 */ /* Hardware timing at 45 IPS 13181 13183 (based on 1580 instr/msec) instr msec SCP instr msec SCP @@ -171,21 +172,23 @@ t_mtrlnt ms_ptr = 0, ms_max = 0; /* buffer ptrs */ passes with the correct data transfer time. */ -int32 msc_btime = 0; /* BOT start delay */ -int32 msc_ctime = 0; /* motion cmd start delay */ -int32 msc_gtime = 0; /* GAP traversal time */ -int32 msc_itime = 0; /* IRG traversal time */ -int32 msc_rtime = 0; /* rewind initiation time */ -int32 msc_xtime = 0; /* data xfer time / word */ +int32 msc_btime = 0; /* BOT start delay */ +int32 msc_ctime = 0; /* motion cmd start delay */ +int32 msc_gtime = 0; /* GAP traversal time */ +int32 msc_itime = 0; /* IRG traversal time */ +int32 msc_rtime = 0; /* rewind initiation time */ +int32 msc_xtime = 0; /* data xfer time / word */ -typedef int32 TIMESET[6]; /* set of controller times */ +typedef int32 TIMESET[6]; /* set of controller times */ int32 *const timers[] = { &msc_btime, &msc_ctime, &msc_gtime, &msc_itime, &msc_rtime, &msc_xtime }; -const TIMESET times[3] = { { 161512, 14044, 175553, 24885, 878, 88 }, /* 13181A */ - { 252800, 17556, 105333, 27387, 878, 44 }, /* 13183A */ - { 1, 1000, 1, 1, 100, 10 } };/* FAST */ +const TIMESET msc_times[3] = { + { 161512, 14044, 175553, 24885, 878, 88 }, /* 13181A */ + { 252800, 17556, 105333, 27387, 878, 44 }, /* 13183A */ + { 1, 1000, 1, 1, 100, 10 } /* FAST */ + }; DEVICE msd_dev, msc_dev; int32 msdio (int32 inst, int32 IR, int32 dat); @@ -204,17 +207,18 @@ t_stat ms_show_timing (FILE *st, UNIT *uptr, int32 val, void *desc); t_stat ms_set_reelsize (UNIT *uptr, int32 val, char *cptr, void *desc); t_stat ms_show_reelsize (FILE *st, UNIT *uptr, int32 val, void *desc); void ms_config_timing (void); - + /* MSD data structures - msd_dev MSD device descriptor - msd_unit MSD unit list - msd_reg MSD register list + msd_dev MSD device descriptor + msd_unit MSD unit list + msd_reg MSD register list */ DIB ms_dib[] = { - { MSD, 0, 0, 0, 0, 0, &msdio }, - { MSC, 0, 0, 0, 0, 0, &mscio } }; + { MSD, 0, 0, 0, 0, 0, &msdio }, + { MSC, 0, 0, 0, 0, 0, &mscio } + }; #define msd_dib ms_dib[0] #define msc_dib ms_dib[1] @@ -222,146 +226,166 @@ DIB ms_dib[] = { 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) }, - { FLDATA (SRQ, msd_dib.srq, 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 } }; + { 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) }, + { FLDATA (SRQ, msd_dib.srq, 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 } }; + { 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, DEV_DISABLE }; + "MSD", &msd_unit, msd_reg, msd_mod, + 1, 10, DB_N_SIZE, 1, 8, 8, + NULL, NULL, &msc_reset, + NULL, NULL, NULL, + &msd_dib, DEV_DISABLE + }; /* MSC data structures - msc_dev MSC device descriptor - msc_unit MSC unit list - msc_reg MSC register list - msc_mod MSC modifier list + 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 | UNIT_OFFLINE, 0) }, - { UDATA (&msc_svc, UNIT_ATTABLE | UNIT_ROABLE | - UNIT_DISABLE | UNIT_OFFLINE, 0) }, - { UDATA (&msc_svc, UNIT_ATTABLE | UNIT_ROABLE | - UNIT_DISABLE | UNIT_OFFLINE, 0) }, - { UDATA (&msc_svc, UNIT_ATTABLE | UNIT_ROABLE | - UNIT_DISABLE | UNIT_OFFLINE, 0) } }; + { UDATA (&msc_svc, UNIT_ATTABLE | UNIT_ROABLE | + UNIT_DISABLE | UNIT_OFFLINE, 0) }, + { UDATA (&msc_svc, UNIT_ATTABLE | UNIT_ROABLE | + UNIT_DISABLE | UNIT_OFFLINE, 0) }, + { UDATA (&msc_svc, UNIT_ATTABLE | UNIT_ROABLE | + UNIT_DISABLE | UNIT_OFFLINE, 0) }, + { UDATA (&msc_svc, UNIT_ATTABLE | UNIT_ROABLE | + UNIT_DISABLE | UNIT_OFFLINE, 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) }, - { FLDATA (SRQ, msc_dib.srq, 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) }, - { URDATA (REEL, msc_unit[0].REEL, 10, 2, 0, MS_NUMDR, REG_HRO) }, - { DRDATA (BTIME, msc_btime, 24), REG_NZ + PV_LEFT }, - { DRDATA (CTIME, msc_ctime, 24), REG_NZ + PV_LEFT }, - { DRDATA (GTIME, msc_gtime, 24), REG_NZ + PV_LEFT }, - { DRDATA (ITIME, msc_itime, 24), REG_NZ + PV_LEFT }, - { DRDATA (RTIME, msc_rtime, 24), REG_NZ + PV_LEFT }, - { DRDATA (XTIME, msc_xtime, 24), REG_NZ + PV_LEFT }, - { FLDATA (TIMING, ms_timing, 0), REG_HRO }, - { FLDATA (STOP_IOE, msc_stopioe, 0) }, - { FLDATA (CTYPE, ms_ctype, 0), REG_HRO }, - { ORDATA (DEVNO, msc_dib.devno, 6), REG_HRO }, - { NULL } }; + { 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) }, + { FLDATA (SRQ, msc_dib.srq, 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) }, + { URDATA (REEL, msc_unit[0].REEL, 10, 2, 0, MS_NUMDR, REG_HRO) }, + { DRDATA (BTIME, msc_btime, 24), REG_NZ + PV_LEFT }, + { DRDATA (CTIME, msc_ctime, 24), REG_NZ + PV_LEFT }, + { DRDATA (GTIME, msc_gtime, 24), REG_NZ + PV_LEFT }, + { DRDATA (ITIME, msc_itime, 24), REG_NZ + PV_LEFT }, + { DRDATA (RTIME, msc_rtime, 24), REG_NZ + PV_LEFT }, + { DRDATA (XTIME, msc_xtime, 24), REG_NZ + PV_LEFT }, + { FLDATA (TIMING, ms_timing, 0), REG_HRO }, + { 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[] = { - { UNIT_OFFLINE, UNIT_OFFLINE, "offline", "OFFLINE", NULL }, - { UNIT_OFFLINE, 0, "online", "ONLINE", msc_online }, - { MTUF_WLK, 0, "write enabled", "WRITEENABLED", NULL }, - { MTUF_WLK, MTUF_WLK, "write locked", "LOCKED", NULL }, - { MTAB_XTD|MTAB_VUN, 0, "REEL", "REEL", - &ms_set_reelsize, &ms_show_reelsize, 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, 0, NULL, "REALTIME", - &ms_set_timing, NULL, NULL }, - { MTAB_XTD | MTAB_VDV, 1, NULL, "FASTTIME", - &ms_set_timing, NULL, NULL }, - { MTAB_XTD | MTAB_VDV, 0, "TIMING", NULL, - NULL, &ms_show_timing, NULL }, - { MTAB_XTD | MTAB_VDV, 1, "DEVNO", "DEVNO", - &hp_setdev, &hp_showdev, &msd_dev }, - { 0 } }; + { UNIT_OFFLINE, UNIT_OFFLINE, "offline", "OFFLINE", NULL }, + { UNIT_OFFLINE, 0, "online", "ONLINE", msc_online }, + { MTUF_WLK, 0, "write enabled", "WRITEENABLED", NULL }, + { MTUF_WLK, MTUF_WLK, "write locked", "LOCKED", NULL }, + { MTAB_XTD|MTAB_VUN, 0, "REEL", "REEL", + &ms_set_reelsize, &ms_show_reelsize, 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, 0, NULL, "REALTIME", + &ms_set_timing, NULL, NULL }, + { MTAB_XTD | MTAB_VDV, 1, NULL, "FASTTIME", + &ms_set_timing, NULL, NULL }, + { MTAB_XTD | MTAB_VDV, 0, "TIMING", NULL, + NULL, &ms_show_timing, 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 | DEV_DEBUG }; - -/* IOT routines */ + "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 | DEV_DEBUG + }; + +/* IO instructions */ 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) { setFSR (devd); } /* STF */ - break; -case ioSFC: /* skip flag clear */ - if (FLG (devd) == 0) PC = (PC + 1) & VAMASK; - break; -case ioSFS: /* skip flag set */ - if (FLG (devd) != 0) PC = (PC + 1) & VAMASK; - break; -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; -case ioEDT: /* DMA end */ - clrFSR (devd); /* same as CLF */ - break; -default: - break; } -if (IR & I_HC) { clrFSR (devd); } /* H/C option */ +devd = IR & I_DEVMASK; /* get device no */ +switch (inst) { /* case on opcode */ + + case ioFLG: /* flag clear/set */ + if ((IR & I_HC) == 0) { setFSR (devd); } /* STF */ + break; + + case ioSFC: /* skip flag clear */ + if (FLG (devd) == 0) PC = (PC + 1) & VAMASK; + break; + + case ioSFS: /* skip flag set */ + if (FLG (devd) != 0) PC = (PC + 1) & VAMASK; + break; + + 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; + + case ioEDT: /* DMA end */ + clrFSR (devd); /* same as CLF */ + break; + + default: + break; + } + +if (IR & I_HC) { clrFSR (devd); } /* H/C option */ return dat; } @@ -371,110 +395,131 @@ int32 i, devc, devd, sched_time; 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 }; + 0, 0, 1, 1, 2, 2, 2, 2, + 3, 3, 3, 3, 3, 3, 3, 3 + }; -devc = IR & I_DEVMASK; /* get device no */ +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) { setFSR (devc); } /* STF */ - break; -case ioSFC: /* skip flag clear */ - if (FLG (devc) == 0) PC = (PC + 1) & VAMASK; - break; -case ioSFS: /* skip flag set */ - if (FLG (devc) != 0) PC = (PC + 1) & VAMASK; - break; -case ioOTX: /* output */ - if (DEBUG_PRS (msc_dev)) - fprintf (sim_deb, ">>MSC OTx: Command = %06o\n", dat); - 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 & ~STA_DYN); /* get card status */ - if ((uptr->flags & UNIT_OFFLINE) == 0) { /* online? */ - dat = dat | uptr->UST; /* add unit status */ - if (sim_is_active (uptr) && /* TBSY unless RWD at BOT */ - !((uptr->FNC & FNF_RWD) && (uptr->UST & STA_BOT))) - dat = dat | STA_TBSY; - if (sim_tape_wrp (uptr)) /* write prot? */ - dat = dat | STA_WLK; - if (uptr->REEL && - sim_tape_eot (uptr, (TCAP << uptr->REEL) << ms_ctype)) - dat = dat | STA_EOT; } - else dat = dat | STA_TBSY | STA_LOCAL; - if (ms_ctype) dat = dat | STA_PE | /* 13183A? */ - (msc_usl << STA_V_SEL); - if (DEBUG_PRS (msc_dev)) - fprintf (sim_deb, ">>MSC LIx: Status = %06o\n", dat); - break; -case ioCTL: /* control clear/set */ - if (IR & I_CTL) { clrCTL (devc); } /* CLC */ - else if (!(msc_sta & STA_REJ)) { /* STC, last cmd rejected? */ - 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 not rew */ - setCTL (devc); /* set CTL for STC */ - setFSR (devc); /* set FLG for completion */ - msc_sta = msc_1st = 0; /* clr ctlr status */ - if (DEBUG_PRS (msc_dev)) - fputs (">>MSC STC: Controller cleared\n", sim_deb); - return SCPE_OK; } - uptr->FNC = msc_buf & 0377; /* save function */ - if (uptr->FNC & FNF_RWD) { /* rewind? */ - if (!(uptr->UST & STA_BOT)) /* not at BOT? */ - uptr->UST = STA_REW; /* set rewinding */ - sched_time = msc_rtime; } /* set response time */ - else { - if (uptr-> UST & STA_BOT) /* at BOT? */ - sched_time = msc_btime; /* use BOT start time */ - else if ((uptr->FNC == FNC_GAP) || (uptr->FNC == FNC_GFM)) - sched_time = msc_gtime; /* use gap traversal time */ - else sched_time = 0; - if (uptr->FNC != FNC_GAP) - sched_time += msc_ctime; /* add base command time */ - if (uptr->FNC & FNF_MOT) /* motion command? */ - uptr->UST = 0; } /* clear BOT status */ - if (msc_buf & ~FNC_SEL) { /* NOP for unit sel alone */ - sim_activate (uptr, sched_time); /* else schedule op */ - if (DEBUG_PRS (msc_dev)) fprintf (sim_deb, - ">>MSC STC: Unit %d command %03o scheduled, time = %d\n", - msc_usl, uptr->FNC, sched_time); } - else if (DEBUG_PRS (msc_dev)) - fputs (">>MSC STC: Unit select (NOP)\n", sim_deb); - msc_sta = STA_BUSY; /* ctrl is busy */ - msc_1st = 1; - setCTL (devc); } /* go */ - break; -case ioEDT: /* DMA end */ - clrFSR (devc); /* same as CLF */ - break; -default: - break; } -if (IR & I_HC) { clrFSR (devc); } /* H/C option */ +switch (inst) { /* case on opcode */ + + case ioFLG: /* flag clear/set */ + if ((IR & I_HC) == 0) { setFSR (devc); } /* STF */ + break; + + case ioSFC: /* skip flag clear */ + if (FLG (devc) == 0) PC = (PC + 1) & VAMASK; + break; + + case ioSFS: /* skip flag set */ + if (FLG (devc) != 0) PC = (PC + 1) & VAMASK; + break; + + case ioOTX: /* output */ + if (DEBUG_PRS (msc_dev)) + fprintf (sim_deb, ">>MSC OTx: Command = %06o\n", dat); + 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 & ~STA_DYN); /* get card status */ + if ((uptr->flags & UNIT_OFFLINE) == 0) { /* online? */ + dat = dat | uptr->UST; /* add unit status */ + if (sim_is_active (uptr) && /* TBSY unless RWD at BOT */ + !((uptr->FNC & FNF_RWD) && (uptr->UST & STA_BOT))) + dat = dat | STA_TBSY; + if (sim_tape_wrp (uptr)) /* write prot? */ + dat = dat | STA_WLK; + if (uptr->REEL && + sim_tape_eot (uptr, (TCAP << uptr->REEL) << ms_ctype)) + dat = dat | STA_EOT; + } + else dat = dat | STA_TBSY | STA_LOCAL; + if (ms_ctype) dat = dat | STA_PE | /* 13183A? */ + (msc_usl << STA_V_SEL); + if (DEBUG_PRS (msc_dev)) + fprintf (sim_deb, ">>MSC LIx: Status = %06o\n", dat); + break; + + case ioCTL: /* control clear/set */ + if (IR & I_CTL) { clrCTL (devc); } /* CLC */ + else if (!(msc_sta & STA_REJ)) { /* STC, last cmd rejected? */ + 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 not rew */ + } + setCTL (devc); /* set CTL for STC */ + setFSR (devc); /* set FLG for completion */ + msc_sta = msc_1st = 0; /* clr ctlr status */ + if (DEBUG_PRS (msc_dev)) + fputs (">>MSC STC: Controller cleared\n", sim_deb); + return SCPE_OK; + } + uptr->FNC = msc_buf & 0377; /* save function */ + if (uptr->FNC & FNF_RWD) { /* rewind? */ + if (!(uptr->UST & STA_BOT)) /* not at BOT? */ + uptr->UST = STA_REW; /* set rewinding */ + sched_time = msc_rtime; /* set response time */ + } + else { + if (uptr-> UST & STA_BOT) /* at BOT? */ + sched_time = msc_btime; /* use BOT start time */ + else if ((uptr->FNC == FNC_GAP) || (uptr->FNC == FNC_GFM)) + sched_time = msc_gtime; /* use gap traversal time */ + else sched_time = 0; + if (uptr->FNC != FNC_GAP) + sched_time += msc_ctime; /* add base command time */ + if (uptr->FNC & FNF_MOT) /* motion command? */ + uptr->UST = 0; /* clear BOT status */ + } + if (msc_buf & ~FNC_SEL) { /* NOP for unit sel alone */ + sim_activate (uptr, sched_time); /* else schedule op */ + if (DEBUG_PRS (msc_dev)) fprintf (sim_deb, + ">>MSC STC: Unit %d command %03o scheduled, time = %d\n", + msc_usl, uptr->FNC, sched_time); + } + else if (DEBUG_PRS (msc_dev)) + fputs (">>MSC STC: Unit select (NOP)\n", sim_deb); + msc_sta = STA_BUSY; /* ctrl is busy */ + msc_1st = 1; + setCTL (devc); /* go */ + } + break; + + case ioEDT: /* DMA end */ + clrFSR (devc); /* same as CLF */ + break; + + default: + break; + } + +if (IR & I_HC) { clrFSR (devc); } /* H/C option */ return dat; } - + /* Unit service If rewind done, reposition to start of tape, set status @@ -489,176 +534,195 @@ int32 devc, devd, unum, cap; t_mtrlnt tbc; t_stat st, r = SCPE_OK; -devc = msc_dib.devno; /* get device nos */ +devc = msc_dib.devno; /* get device nos */ devd = msd_dib.devno; -unum = uptr - msc_dev.units; /* get unit number */ +unum = uptr - msc_dev.units; /* get unit number */ if ((uptr->FNC != FNC_RWS) && (uptr->flags & UNIT_OFFLINE)) { /* offline? */ - msc_sta = (msc_sta | STA_REJ) & ~STA_BUSY; /* reject */ - setFSR (devc); /* set cch flg */ - return IORETURN (msc_stopioe, SCPE_UNATT); } + msc_sta = (msc_sta | STA_REJ) & ~STA_BUSY; /* reject */ + setFSR (devc); /* set cch flg */ + return IORETURN (msc_stopioe, SCPE_UNATT); + } -switch (uptr->FNC) { /* case on function */ +switch (uptr->FNC) { /* case on function */ -case FNC_RWS: /* rewind offline */ - sim_tape_rewind (uptr); /* rewind tape */ - uptr->flags = uptr->flags | UNIT_OFFLINE; /* set offline */ - uptr->UST = STA_BOT; /* BOT when online again */ - break; /* we're done */ + case FNC_RWS: /* rewind offline */ + sim_tape_rewind (uptr); /* rewind tape */ + uptr->flags = uptr->flags | UNIT_OFFLINE; /* set offline */ + uptr->UST = STA_BOT; /* BOT when online again */ + break; /* we're done */ -case FNC_REW: /* rewind */ - if (uptr->UST & STA_REW) { /* rewind in prog? */ - uptr->FNC |= FNC_CMPL; /* set compl state */ - sim_activate (uptr, msc_ctime); } /* sched completion */ - break; /* anyway, ctrl done */ + case FNC_REW: /* rewind */ + if (uptr->UST & STA_REW) { /* rewind in prog? */ + uptr->FNC |= FNC_CMPL; /* set compl state */ + sim_activate (uptr, msc_ctime); /* sched completion */ + } + break; /* anyway, ctrl done */ -case FNC_REW | FNC_CMPL: /* complete rewind */ - sim_tape_rewind (uptr); /* rewind tape */ - uptr->UST = STA_BOT; /* set BOT status */ - return SCPE_OK; /* drive is free */ + case FNC_REW | FNC_CMPL: /* complete rewind */ + sim_tape_rewind (uptr); /* rewind tape */ + uptr->UST = STA_BOT; /* set BOT status */ + return SCPE_OK; /* drive is free */ -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_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_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_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_BSR: /* space reverse */ + 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: - cap = (TCAP << uptr->REEL) << ms_ctype; - while ((st = sim_tape_sprecf (uptr, &tbc)) == MTSE_OK) { - if (uptr->REEL && sim_tape_eot (uptr, cap)) - break; } /* EOT stops */ - r = ms_map_err (uptr, st); /* map error */ - break; + case FNC_FSF: /* space fwd file */ + cap = (TCAP << uptr->REEL) << ms_ctype; + while ((st = sim_tape_sprecf (uptr, &tbc)) == MTSE_OK) { + if (uptr->REEL && sim_tape_eot (uptr, cap)) + break; /* EOT stops */ + } + r = ms_map_err (uptr, st); /* map error */ + break; -case FNC_BSF: - while ((st = sim_tape_sprecr (uptr, &tbc)) == MTSE_OK) ; - r = ms_map_err (uptr, st); /* map error */ - break; - -/* Unit service, continued */ + case FNC_BSF: /* space rev file */ + while ((st = sim_tape_sprecr (uptr, &tbc)) == MTSE_OK) ; + r = ms_map_err (uptr, st); /* map error */ + break; -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_itime); /* sched IRG */ - uptr->FNC |= FNC_CMPL; /* set completion */ - return SCPE_OK; } - break; } /* err, done */ - if (ms_ctype) msc_sta = msc_sta | STA_ODD; /* set ODD for 13183A */ - if (DEBUG_PRS (msc_dev)) fprintf (sim_deb, - ">>MSC svc: Unit %d read %d word record\n", unum, ms_max / 2); - } - if (CTL (devd) && (ms_ptr < ms_max)) { /* DCH on, more data? */ - if (FLG (devd)) msc_sta = msc_sta | STA_TIM | STA_PAR; - msd_buf = ((uint16) msxb[ms_ptr] << 8) | - ((ms_ptr + 1 == ms_max) ? 0 : msxb[ms_ptr + 1]); - ms_ptr = ms_ptr + 2; - setFSR (devd); /* set dch flg */ - sim_activate (uptr, msc_xtime); /* re-activate */ - return SCPE_OK; } - if (ms_max & 1) msc_sta = msc_sta | STA_ODD; /* set ODD by rec len */ - else msc_sta = msc_sta & ~STA_ODD; - sim_activate (uptr, msc_itime); /* sched IRG */ - if (uptr->FNC == FNC_RFF) msc_1st = 1; /* diagnostic? */ - else uptr->FNC |= FNC_CMPL; /* set completion */ - return SCPE_OK; + 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_itime); /* sched IRG */ + uptr->FNC |= FNC_CMPL; /* set completion */ + return SCPE_OK; + } + break; /* err, done */ + } + if (ms_ctype) msc_sta = msc_sta | STA_ODD; /* set ODD for 13183A */ + if (DEBUG_PRS (msc_dev)) fprintf (sim_deb, + ">>MSC svc: Unit %d read %d word record\n", unum, ms_max / 2); + } + if (CTL (devd) && (ms_ptr < ms_max)) { /* DCH on, more data? */ + if (FLG (devd)) msc_sta = msc_sta | STA_TIM | STA_PAR; + msd_buf = ((uint16) msxb[ms_ptr] << 8) | + ((ms_ptr + 1 == ms_max) ? 0 : msxb[ms_ptr + 1]); + ms_ptr = ms_ptr + 2; + setFSR (devd); /* set dch flg */ + sim_activate (uptr, msc_xtime); /* re-activate */ + return SCPE_OK; + } + if (ms_max & 1) msc_sta = msc_sta | STA_ODD; /* set ODD by rec len */ + else msc_sta = msc_sta & ~STA_ODD; + sim_activate (uptr, msc_itime); /* sched IRG */ + if (uptr->FNC == FNC_RFF) msc_1st = 1; /* diagnostic? */ + else uptr->FNC |= FNC_CMPL; /* set completion */ + 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? */ - setFSR (devd); /* set dch flag */ - sim_activate (uptr, msc_xtime); /* re-activate */ - return SCPE_OK; } - if (ms_ptr) { /* any data? write */ - if (DEBUG_PRS (msc_dev)) fprintf (sim_deb, - ">>MSC svc: Unit %d wrote %d word record\n", unum, ms_ptr / 2); - if (st = sim_tape_wrrecf (uptr, msxb, ms_ptr)) { /* write, err? */ - r = ms_map_err (uptr, st); /* map error */ - break; } } - sim_activate (uptr, msc_itime); /* sched IRG */ - uptr->FNC |= FNC_CMPL; /* set completion */ - 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? */ + setFSR (devd); /* set dch flag */ + sim_activate (uptr, msc_xtime); /* re-activate */ + return SCPE_OK; + } + if (ms_ptr) { /* any data? write */ + if (DEBUG_PRS (msc_dev)) fprintf (sim_deb, + ">>MSC svc: Unit %d wrote %d word record\n", unum, ms_ptr / 2); + if (st = sim_tape_wrrecf (uptr, msxb, ms_ptr)) { /* write, err? */ + r = ms_map_err (uptr, st); /* map error */ + break; + } + } + sim_activate (uptr, msc_itime); /* sched IRG */ + uptr->FNC |= FNC_CMPL; /* set completion */ + return SCPE_OK; -default: /* unknown */ - break; } + default: /* unknown */ + break; + } -setFSR (devc); /* set cch flg */ -msc_sta = msc_sta & ~STA_BUSY; /* update status */ +setFSR (devc); /* set cch flg */ +msc_sta = msc_sta & ~STA_BUSY; /* update status */ if (DEBUG_PRS (msc_dev)) fprintf (sim_deb, - ">>MSC svc: Unit %d command %03o complete\n", unum, uptr->FNC & 0377); + ">>MSC svc: Unit %d command %03o complete\n", unum, uptr->FNC & 0377); return r; } - + /* Map tape error status */ t_stat ms_map_err (UNIT *uptr, t_stat st) { -int32 unum = uptr - msc_dev.units; /* get unit number */ +int32 unum = uptr - msc_dev.units; /* get unit number */ if (DEBUG_PRS (msc_dev)) fprintf (sim_deb, - ">>MSC err: Unit %d tape library status = %d\n", unum, st); + ">>MSC err: Unit %d tape library status = %d\n", unum, 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_EOM: /* end of medium */ -case MTSE_TMK: /* end of file */ - msc_sta = msc_sta | STA_EOF | (ms_ctype ? 0 : STA_ODD); - break; /* EOF also sets ODD for 13181A */ -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 */ - msc_sta = msc_sta | STA_PAR; /* error */ - break; -case MTSE_BOT: /* reverse into BOT */ - msc_sta = msc_sta | STA_BOT; /* set BOT status */ - break; -case MTSE_WRP: /* write protect */ - msc_sta = msc_sta | STA_REJ; /* reject */ - break; } + + 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_EOM: /* end of medium */ + case MTSE_TMK: /* end of file */ + msc_sta = msc_sta | STA_EOF | (ms_ctype ? 0 : STA_ODD); + break; /* EOF also sets ODD for 13181A */ + + 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 */ + msc_sta = msc_sta | STA_PAR; /* error */ + break; + + case MTSE_BOT: /* reverse into BOT */ + msc_sta = msc_sta | STA_BOT; /* set BOT 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) @@ -666,23 +730,24 @@ t_stat msc_reset (DEVICE *dptr) int32 i; UNIT *uptr; -hp_enbdis_pair (dptr, /* make pair cons */ - (dptr == &msd_dev)? &msc_dev: &msd_dev); +hp_enbdis_pair (dptr, /* make pair cons */ + (dptr == &msd_dev)? &msc_dev: &msd_dev); 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 */ -msc_dib.srq = msd_dib.srq = 1; /* srq follows flg */ +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 */ +msc_dib.srq = msd_dib.srq = 1; /* srq follows flg */ for (i = 0; i < MS_NUMDR; i++) { - uptr = msc_dev.units + i; - sim_tape_reset (uptr); - sim_cancel (uptr); - if ((uptr->flags & UNIT_ATT) && sim_tape_bot (uptr)) - uptr->UST = STA_BOT; - else uptr->UST = 0; } + uptr = msc_dev.units + i; + sim_tape_reset (uptr); + sim_cancel (uptr); + if ((uptr->flags & UNIT_ATT) && sim_tape_bot (uptr)) + uptr->UST = STA_BOT; + else uptr->UST = 0; + } ms_config_timing (); return SCPE_OK; } @@ -693,10 +758,11 @@ t_stat msc_attach (UNIT *uptr, char *cptr) { t_stat r; -r = sim_tape_attach (uptr, cptr); /* attach unit */ +r = sim_tape_attach (uptr, cptr); /* attach unit */ if (r == SCPE_OK) { - uptr->flags = uptr->flags & ~UNIT_OFFLINE; /* set online */ - uptr->UST = STA_BOT; } /* tape starts at BOT */ + uptr->flags = uptr->flags & ~UNIT_OFFLINE; /* set online */ + uptr->UST = STA_BOT; /* tape starts at BOT */ + } return r; } @@ -704,9 +770,9 @@ return r; t_stat msc_detach (UNIT* uptr) { -uptr->UST = 0; /* update status */ -uptr->flags = uptr->flags | UNIT_OFFLINE; /* set offline */ -return sim_tape_detach (uptr); /* detach unit */ +uptr->UST = 0; /* update status */ +uptr->flags = uptr->flags | UNIT_OFFLINE; /* set offline */ +return sim_tape_detach (uptr); /* detach unit */ } /* Online routine */ @@ -723,9 +789,9 @@ void ms_config_timing (void) { int32 i, tset; -tset = (ms_timing << 1) | (ms_timing? 0 : ms_ctype); /* select timing set */ +tset = (ms_timing << 1) | (ms_timing? 0 : ms_ctype); /* select timing set */ for (i = 0; i < (sizeof (timers) / sizeof (timers[0])); i++) - *timers[i] = times[tset][i]; /* assign times */ + *timers[i] = msc_times[tset][i]; /* assign times */ } /* Set controller timing */ @@ -755,9 +821,10 @@ 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; } + if (msc_unit[i].flags & UNIT_ATT) return SCPE_ALATT; + } ms_ctype = val; -ms_config_timing (); /* update for new type */ +ms_config_timing (); /* update for new type */ return SCPE_OK; } @@ -781,20 +848,27 @@ if (cptr == NULL) return SCPE_ARG; reel = (int32) get_uint (cptr, 10, 2400, &status); if (status != SCPE_OK) return status; else switch (reel) { - case 0: - uptr->REEL = 0; /* type 0 = unlimited */ - break; - case 600: - uptr->REEL = 1; /* type 1 = 600 foot */ - break; - case 1200: - uptr->REEL = 2; /* type 2 = 1200 foot */ - break; - case 2400: - uptr->REEL = 3; /* type 3 = 2400 foot */ - break; - default: - return SCPE_ARG; } + + case 0: + uptr->REEL = 0; /* type 0 = unlimited */ + break; + + case 600: + uptr->REEL = 1; /* type 1 = 600 foot */ + break; + + case 1200: + uptr->REEL = 2; /* type 2 = 1200 foot */ + break; + + case 2400: + uptr->REEL = 3; /* type 3 = 2400 foot */ + break; + + default: + return SCPE_ARG; + } + return SCPE_OK; } @@ -810,81 +884,82 @@ return SCPE_OK; /* 7970B/7970E bootstrap routine (HP 12992D ROM) */ const uint16 ms_rom[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 */ - 0102311, /* 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 */ - 0103710, /* STC DC,C ; start dch */ - 0102211, /* SFC CC ; read done? */ - 0027752, /* JMP STAT ; no, get stat */ - 0102310, /* SFS DC ; any data? */ - 0027717, /* JMP *-3 ; wait */ - 0107510, /* LIB DC,C ; get rec cnt */ - 0005727, /* BLF,BLF ; move to lower */ - 0007000, /* CMB ; make neg */ - 0077775, /* STA WC ; save */ - 0102211, /* SFC CC ; read done? */ - 0027752, /* JMP STAT ; no, get stat */ - 0102310, /* SFS DC ; any data? */ - 0027727, /* JMP *-3 ; wait */ - 0107510, /* 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 */ - 0102310, /* SFS DC ; any data? */ - 0027742, /* JMP *-1 ; wait */ - 0107510, /* 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 */ - 0102511, /*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 */ - 0106611, /* OTB CC ; output cmd */ - 0102511, /* LIA CC ; check for reject */ - 0001323, /* RAR,RAR */ - 0001310, /* RAR,SLA */ - 0027763, /* JMP CMD+1 ; try again */ - 0103711, /* 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 }; + 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 */ + 0102311, /* 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 */ + 0103710, /* STC DC,C ; start dch */ + 0102211, /* SFC CC ; read done? */ + 0027752, /* JMP STAT ; no, get stat */ + 0102310, /* SFS DC ; any data? */ + 0027717, /* JMP *-3 ; wait */ + 0107510, /* LIB DC,C ; get rec cnt */ + 0005727, /* BLF,BLF ; move to lower */ + 0007000, /* CMB ; make neg */ + 0077775, /* STA WC ; save */ + 0102211, /* SFC CC ; read done? */ + 0027752, /* JMP STAT ; no, get stat */ + 0102310, /* SFS DC ; any data? */ + 0027727, /* JMP *-3 ; wait */ + 0107510, /* 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 */ + 0102310, /* SFS DC ; any data? */ + 0027742, /* JMP *-1 ; wait */ + 0107510, /* 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 */ + 0102511, /*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 */ + 0106611, /* OTB CC ; output cmd */ + 0102511, /* LIA CC ; check for reject */ + 0001323, /* RAR,RAR */ + 0001310, /* RAR,SLA */ + 0027763, /* JMP CMD+1 ; try again */ + 0103711, /* 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 dev; extern uint32 saved_AR; -if (unitno != 0) return SCPE_NOFNC; /* only unit 0 */ -dev = msd_dib.devno; /* get data chan dev */ -if (ibl_copy (ms_rom, dev)) return SCPE_IERR; /* copy boot to memory */ -SR = (SR & IBL_OPT) | IBL_MS | (dev << IBL_V_DEV); /* set SR */ -if ((sim_switches & SWMASK ('S')) && saved_AR) SR = SR | 1; /* skip? */ +if (unitno != 0) return SCPE_NOFNC; /* only unit 0 */ +dev = msd_dib.devno; /* get data chan dev */ +if (ibl_copy (ms_rom, dev)) return SCPE_IERR; /* copy boot to memory */ +SR = (SR & IBL_OPT) | IBL_MS | (dev << IBL_V_DEV); /* set SR */ +if ((sim_switches & SWMASK ('S')) && saved_AR) SR = SR | 1; /* skip? */ return SCPE_OK; } diff --git a/HP2100/hp2100_mt.c b/HP2100/hp2100_mt.c index efd9220b..de1d31fd 100644 --- a/HP2100/hp2100_mt.c +++ b/HP2100/hp2100_mt.c @@ -19,41 +19,41 @@ 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 + 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 + mt 12559A 3030 nine track magnetic tape - 07-Oct-04 JDB Allow enable/disable from either device - 14-Aug-04 RMS Modified handling of end of medium (suggested by Dave Bryan) - 06-Jul-04 RMS Fixed spurious timing error after CLC (found by Dave Bryan) - 26-Apr-04 RMS Fixed SFS x,C and SFC x,C - Implemented DMA SRQ (follows FLG) - 21-Dec-03 RMS Adjusted msc_ctime for TSB (from Mike Gemeny) - 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 + 07-Oct-04 JDB Allow enable/disable from either device + 14-Aug-04 RMS Modified handling of end of medium (suggested by Dave Bryan) + 06-Jul-04 RMS Fixed spurious timing error after CLC (found by Dave Bryan) + 26-Apr-04 RMS Fixed SFS x,C and SFC x,C + Implemented DMA SRQ (follows FLG) + 21-Dec-03 RMS Adjusted msc_ctime for TSB (from Mike Gemeny) + 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 + 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. @@ -65,46 +65,46 @@ #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 */ +#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 */ +#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) */ - +#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], dev_srq[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 = 40; /* 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 */ +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 = 40; /* 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 }; @@ -120,14 +120,15 @@ 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 + mtd_dev MTD device descriptor + mtd_unit MTD unit list + mtd_reg MTD register list */ DIB mt_dib[] = { - { MTD, 0, 0, 0, 0, 0, &mtdio }, - { MTC, 0, 0, 0, 0, 0, &mtcio } }; + { MTD, 0, 0, 0, 0, 0, &mtdio }, + { MTC, 0, 0, 0, 0, 0, &mtcio } + }; #define mtd_dib mt_dib[0] #define mtc_dib mt_dib[1] @@ -135,106 +136,122 @@ DIB mt_dib[] = { 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) }, - { FLDATA (SRQ, mtd_dib.srq, 0) }, - { 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 } }; + { 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) }, + { FLDATA (SRQ, mtd_dib.srq, 0) }, + { 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 } }; + { 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, &mtd_reset, - NULL, NULL, NULL, - &mtd_dib, DEV_DISABLE | DEV_DIS }; + "MTD", &mtd_unit, mtd_reg, mtd_mod, + 1, 10, 16, 1, 8, 8, + NULL, NULL, &mtd_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 + 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 (SRQ, mtc_dib.srq, 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 } }; + { 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 (SRQ, mtc_dib.srq, 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 } }; + { 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 */ + "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 + }; + +/* IO instructions */ 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) { setFSR (devd); } /* STF */ - break; -case ioSFC: /* skip flag clear */ - if (FLG (devd) == 0) PC = (PC + 1) & VAMASK; - break; -case ioSFS: /* skip flag set */ - if (FLG (devd) != 0) PC = (PC + 1) & VAMASK; - break; -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) { clrFSR (devd); } /* H/C option */ +devd = IR & I_DEVMASK; /* get device no */ +switch (inst) { /* case on opcode */ + + case ioFLG: /* flag clear/set */ + if ((IR & I_HC) == 0) { setFSR (devd); } /* STF */ + break; + + case ioSFC: /* skip flag clear */ + if (FLG (devd) == 0) PC = (PC + 1) & VAMASK; + break; + + case ioSFS: /* skip flag set */ + if (FLG (devd) != 0) PC = (PC + 1) & VAMASK; + break; + + 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) { clrFSR (devd); } /* H/C option */ return dat; } @@ -243,71 +260,84 @@ int32 mtcio (int32 inst, int32 IR, int32 dat) int32 i, devc, devd, valid; t_stat st; -devc = IR & I_DEVMASK; /* get device no */ +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) { setFSR (devc); } /* STF */ - break; -case ioSFC: /* skip flag clear */ - if (FLG (devc) == 0) PC = (PC + 1) & VAMASK; - break; -case ioSFS: /* skip flag set */ - if (FLG (devc) != 0) PC = (PC + 1) & VAMASK; - break; -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 */ - clrFSR (devc); - clrCTL (devd); - clrFSR (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 */ - clrFSR (devc); /* clear flags */ - clrFSR (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) { clrFSR (devc); } /* H/C option */ +switch (inst) { /* case on opcode */ + + case ioFLG: /* flag clear/set */ + if ((IR & I_HC) == 0) { setFSR (devc); } /* STF */ + break; + + case ioSFC: /* skip flag clear */ + if (FLG (devc) == 0) PC = (PC + 1) & VAMASK; + break; + + case ioSFS: /* skip flag set */ + if (FLG (devc) != 0) PC = (PC + 1) & VAMASK; + break; + + 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 */ + clrFSR (devc); + clrCTL (devd); + clrFSR (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 */ + clrFSR (devc); /* clear flags */ + clrFSR (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) { clrFSR (devc); } /* H/C option */ return dat; } - + /* Unit service If rewind done, reposition to start of tape, set status @@ -322,154 +352,172 @@ int32 devc, devd; t_mtrlnt tbc; t_stat st, r = SCPE_OK; -devc = mtc_dib.devno; /* get device nos */ +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 */ - setFSR (devc); /* set cch flg */ - return IORETURN (mtc_stopioe, SCPE_UNATT); } +if ((mtc_unit.flags & UNIT_ATT) == 0) { /* offline? */ + mtc_sta = STA_LOCAL | STA_REJ; /* rejected */ + setFSR (devc); /* set cch flg */ + return IORETURN (mtc_stopioe, SCPE_UNATT); + } -switch (mtc_fnc) { /* case on function */ +switch (mtc_fnc) { /* case on function */ -case FNC_REW: /* rewind */ - sim_tape_rewind (uptr); /* BOT */ - mtc_sta = STA_BOT; /* update status */ - break; + 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_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_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_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_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_BSR: /* space reverse */ + if (st = sim_tape_sprecr (uptr, &tbc)) /* space rec rev, err? */ + r = mt_map_err (uptr, st); /* map error */ + break; -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 (mtc_dtf && (mt_ptr < mt_max)) { /* more chars? */ - if (FLG (devd)) mtc_sta = mtc_sta | STA_TIM; - mtc_unit.buf = mtxb[mt_ptr++]; /* fetch next */ - setFSR (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_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 (mtc_dtf && (mt_ptr < mt_max)) { /* more chars? */ + if (FLG (devd)) mtc_sta = mtc_sta | STA_TIM; + mtc_unit.buf = mtxb[mt_ptr++]; /* fetch next */ + setFSR (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? */ - setFSR (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; + 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? */ + setFSR (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; } + default: /* unknown */ + break; + } -setFSR (devc); /* set cch flg */ -mtc_sta = mtc_sta & ~STA_BUSY; /* not busy */ +setFSR (devc); /* set cch flg */ +mtc_sta = mtc_sta & ~STA_BUSY; /* not busy */ return r; } - + /* 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_EOM: /* end of medium */ -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 */ - 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; } + + 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_EOM: /* end of medium */ + 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 */ + 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 mtd_reset (DEVICE *dptr) { -hp_enbdis_pair (&mtd_dev, &mtc_dev); /* make pair cons */ -return mtc_reset (dptr); /* do common reset */ +hp_enbdis_pair (&mtd_dev, &mtc_dev); /* make pair cons */ +return mtc_reset (dptr); /* do common reset */ } t_stat mtc_reset (DEVICE *dptr) { -hp_enbdis_pair (&mtc_dev, &mtd_dev); /* make pair cons */ +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 */ -mtc_dib.srq = mtd_dib.srq = 0; /* srq follows flg */ -sim_cancel (&mtc_unit); /* cancel activity */ +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 */ +mtc_dib.srq = mtd_dib.srq = 0; /* srq follows flg */ +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); + (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; } @@ -480,8 +528,8 @@ 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 */ +r = sim_tape_attach (uptr, cptr); /* attach unit */ +if (r != SCPE_OK) return r; /* update status */ mtc_sta = STA_BOT; return r; } @@ -490,6 +538,6 @@ return r; t_stat mtc_detach (UNIT* uptr) { -mtc_sta = 0; /* update status */ -return sim_tape_detach (uptr); /* detach unit */ +mtc_sta = 0; /* update status */ +return sim_tape_detach (uptr); /* detach unit */ } diff --git a/HP2100/hp2100_mux.c b/HP2100/hp2100_mux.c index 09920b79..78b07e43 100644 --- a/HP2100/hp2100_mux.c +++ b/HP2100/hp2100_mux.c @@ -1,6 +1,6 @@ /* hp2100_mux.c: HP 2100 12920A terminal multiplexor simulator - Copyright (c) 2002-2004, Robert M Supnik + Copyright (c) 2002-2005, 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"), @@ -19,26 +19,27 @@ 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 + 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 + mux,muxl,muxc 12920A terminal multiplexor - 07-Oct-04 JDB Allow enable/disable from any device - 26-Apr-04 RMS Fixed SFS x,C and SFC x,C - Implemented DMA SRQ (follows FLG) - 05-Jan-04 RMS Revised for tmxr library changes - 21-Dec-03 RMS Added invalid character screening for TSB (from Mike Gemeny) - 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 + 29-Jun-05 RMS Added SET MUXLn DISCONNECT + 07-Oct-04 JDB Allow enable/disable from any device + 26-Apr-04 RMS Fixed SFS x,C and SFC x,C + Implemented DMA SRQ (follows FLG) + 05-Jan-04 RMS Revised for tmxr library changes + 21-Dec-03 RMS Added invalid character screening for TSB (from Mike Gemeny) + 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) + 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. @@ -53,114 +54,114 @@ #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 +#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) +#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 */ +#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 */ +#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 */ +#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 */ +#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_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) -#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], dev_srq[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 */ +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, mux_ldsc }; /* mux descriptor */ +TMLN mux_ldsc[MUX_LINES] = { 0 }; /* line descriptors */ +TMXR mux_desc = { MUX_LINES, 0, 0, mux_ldsc }; /* mux descriptor */ DEVICE muxl_dev, muxu_dev, muxc_dev; int32 muxlio (int32 inst, int32 IR, int32 dat); @@ -178,144 +179,155 @@ 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 */ + 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) +#define RCV_PAR(x) (odd_par[(x) & 0377]? LIL_PAR: 0) DIB mux_dib[] = { - { MUXL, 0, 0, 0, 0, 0, &muxlio }, - { MUXU, 0, 0, 0, 0, 0, &muxuio } }; + { MUXL, 0, 0, 0, 0, 0, &muxlio }, + { MUXU, 0, 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 + 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 }, - { FLDATA (SRQ, muxu_dib.srq, 0), REG_HRO }, - { ORDATA (DEVNO, muxu_dib.devno, 6), REG_HRO }, - { NULL } }; + { 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 }, + { FLDATA (SRQ, muxu_dib.srq, 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 } }; + { 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, &muxc_reset, - NULL, &mux_attach, &mux_detach, - &muxu_dib, DEV_NET | DEV_DISABLE }; - + "MUX", &muxu_unit, muxu_reg, muxu_mod, + 1, 10, 31, 1, 8, 8, + &tmxr_ex, &tmxr_dep, &muxc_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 + 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 }, + { 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_VUN|MTAB_NC, 0, "LOG", "LOG", - &tmxr_set_log, &tmxr_show_log, &mux_desc }, - { MTAB_XTD|MTAB_VUN|MTAB_NC, 0, NULL, "NOLOG", - &tmxr_set_nolog, NULL, &mux_desc }, - { MTAB_XTD|MTAB_VDV, 1, "DEVNO", "DEVNO", - &hp_setdev, &hp_showdev, &muxl_dev }, - { 0 } }; + { 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_VUN, 0, NULL, "DISCONNECT", + &tmxr_dscln, NULL, &mux_desc }, + { MTAB_XTD|MTAB_VUN|MTAB_NC, 0, "LOG", "LOG", + &tmxr_set_log, &tmxr_show_log, &mux_desc }, + { MTAB_XTD|MTAB_VUN|MTAB_NC, 0, NULL, "NOLOG", + &tmxr_set_nolog, NULL, &mux_desc }, + { 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) }, - { FLDATA (SRQ, muxl_dib.srq, 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 } }; + { 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) }, + { FLDATA (SRQ, muxl_dib.srq, 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, &muxc_reset, - NULL, NULL, NULL, - &muxl_dib, DEV_DISABLE }; - + "MUXL", muxl_unit, muxl_reg, muxl_mod, + MUX_LINES, 10, 31, 1, 8, 8, + NULL, NULL, &muxc_reset, + NULL, NULL, NULL, + &muxl_dib, DEV_DISABLE + }; + /* MUXM data structures - muxc_dev MUXM device descriptor - muxc_unit MUXM unit descriptor - muxc_reg MUXM register list - muxc_mod MUXM modifiers list + 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, 0, &muxcio }; @@ -323,158 +335,192 @@ DIB muxc_dib = { MUXC, 0, 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 (SRQ, muxc_dib.srq, 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 } }; + { 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 (SRQ, muxc_dib.srq, 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 } }; + { 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, &muxc_reset, - NULL, NULL, NULL, - &muxc_dib, DEV_DISABLE }; - -/* IOT routines: data cards */ + "MUXM", &muxc_unit, muxc_reg, muxc_mod, + 1, 10, 31, 1, 8, 8, + NULL, NULL, &muxc_reset, + NULL, NULL, NULL, + &muxc_dib, DEV_DISABLE + }; + +/* IO instructions: 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) { setFSR (dev); } /* STF */ - break; -case ioSFC: /* skip flag clear */ - if (FLG (dev) == 0) PC = (PC + 1) & VAMASK; - break; -case ioSFS: /* skip flag set */ - if (FLG (dev) != 0) PC = (PC + 1) & VAMASK; - break; -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 */ - clrFSR (dev); /* clear flag */ - mux_data_int (); } /* look for new int */ +dev = IR & I_DEVMASK; /* get device no */ +switch (inst) { /* case on opcode */ + + case ioFLG: /* flag clear/set */ + if ((IR & I_HC) == 0) { setFSR (dev); } /* STF */ + break; + + case ioSFC: /* skip flag clear */ + if (FLG (dev) == 0) PC = (PC + 1) & VAMASK; + break; + + case ioSFS: /* skip flag set */ + if (FLG (dev) != 0) PC = (PC + 1) & VAMASK; + break; + + 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 */ + clrFSR (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; } +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 */ + +/* IO instructions: 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) { setFSR (dev); } /* STF */ - break; -case ioSFC: /* skip flag clear */ - if (FLG (dev) == 0) PC = (PC + 1) & VAMASK; - break; -case ioSFS: /* skip flag set */ - if (FLG (dev) != 0) PC = (PC + 1) & VAMASK; - break; -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_linemsg (&mux_ldsc[ln], "\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 */ - clrFSR (dev); /* clear flag */ - mux_ctrl_int (); } /* look for new int */ +dev = IR & I_DEVMASK; /* get device no */ +switch (inst) { /* case on opcode */ + + case ioFLG: /* flag clear/set */ + if ((IR & I_HC) == 0) { setFSR (dev); } /* STF */ + break; + + case ioSFC: /* skip flag clear */ + if (FLG (dev) == 0) PC = (PC + 1) & VAMASK; + break; + + case ioSFS: /* skip flag set */ + if (FLG (dev) != 0) PC = (PC + 1) & VAMASK; + break; + + 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_linemsg (&mux_ldsc[ln], "\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 */ + clrFSR (dev); /* clear flag */ + mux_ctrl_int (); /* look for new int */ + } return dat; } - + /* Unit service - receive side Poll for new connections @@ -485,42 +531,47 @@ 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 */ +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; } @@ -528,64 +579,75 @@ return SCPE_OK; t_stat muxo_svc (UNIT *uptr) { -int32 c, ln = uptr - muxl_unit; /* line # */ +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 */ - if (!(muxl_unit[ln].flags & UNIT_8B) && /* not transparent? */ - (c != 0x7f) && (c != 0x13) && /* not del, ^S? */ - (c != 0x11) && (c != 0x5)) /* not ^Q, ^E? */ - 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 */ +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 */ + if (!(muxl_unit[ln].flags & UNIT_8B) && /* not transparent? */ + (c != 0x7f) && (c != 0x13) && /* not del, ^S? */ + (c != 0x11) && (c != 0x5)) /* not ^Q, ^E? */ + 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; - setFSR (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; - setFSR (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; - setFSR (muxl_dib.devno); - return; } } +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; + setFSR (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; + setFSR (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; + setFSR (muxl_dib.devno); + return; + } + } return; } @@ -597,10 +659,12 @@ 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? */ - setFSR (muxc_dib.devno); /* set flag */ - break; } } + muxc_chan = (muxc_chan + 1) & LIC_M_CHAN; /* step channel */ + if (LIC_TSTI (muxc_chan)) { /* status change? */ + setFSR (muxc_dib.devno); /* set flag */ + break; + } + } return; } @@ -611,28 +675,31 @@ 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; } } + 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_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); +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; } @@ -643,26 +710,32 @@ t_stat muxc_reset (DEVICE *dptr) { int32 i, t; -if (dptr == &muxc_dev) { /* make all consistent */ - hp_enbdis_pair (dptr, &muxl_dev); - hp_enbdis_pair (dptr, &muxu_dev); } +if (dptr == &muxc_dev) { /* make all consistent */ + hp_enbdis_pair (dptr, &muxl_dev); + hp_enbdis_pair (dptr, &muxu_dev); + } else if (dptr == &muxl_dev) { - hp_enbdis_pair (dptr, &muxc_dev); - hp_enbdis_pair (dptr, &muxu_dev); } -else { hp_enbdis_pair (dptr, &muxc_dev); - hp_enbdis_pair (dptr, &muxl_dev); } -muxl_dib.cmd = muxl_dib.ctl = 0; /* init lower */ + hp_enbdis_pair (dptr, &muxc_dev); + hp_enbdis_pair (dptr, &muxu_dev); + } +else { + hp_enbdis_pair (dptr, &muxc_dev); + hp_enbdis_pair (dptr, &muxl_dev); + } +muxl_dib.cmd = muxl_dib.ctl = 0; /* init lower */ muxl_dib.flg = muxl_dib.fbf = muxl_dib.srq = 1; -muxu_dib.cmd = muxu_dib.ctl = 0; /* upper not */ -muxu_dib.flg = muxu_dib.fbf = muxu_dib.srq = 0; /* implemented */ -muxc_dib.cmd = muxc_dib.ctl = 0; /* init ctrl */ +muxu_dib.cmd = muxu_dib.ctl = 0; /* upper not */ +muxu_dib.flg = muxu_dib.fbf = muxu_dib.srq = 0; /* implemented */ +muxc_dib.cmd = muxc_dib.ctl = 0; /* init ctrl */ muxc_dib.flg = muxc_dib.fbf = muxc_dib.srq = 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 */ +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_reset_ln (i); return SCPE_OK; } @@ -674,10 +747,10 @@ 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 */ +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 */ +sim_activate (uptr, t); /* start poll */ return SCPE_OK; } @@ -688,9 +761,9 @@ 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 */ +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; } @@ -710,14 +783,17 @@ return SCPE_OK; t_stat mux_show (FILE *st, UNIT *uptr, int32 val, void *desc) { -int32 i; +int32 i, t; -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); } } } +for (i = t = 0; i < MUX_LINES; i++) t = t + (mux_ldsc[i].conn != 0); +if (t) { + 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 index 371afa27..b133bedc 100644 --- a/HP2100/hp2100_stddev.c +++ b/HP2100/hp2100_stddev.c @@ -1,6 +1,6 @@ /* hp2100_stddev.c: HP2100 standard devices simulator - Copyright (c) 1993-2004, Robert M. Supnik + Copyright (c) 1993-2005, 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"), @@ -19,43 +19,43 @@ 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 + 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 interface - ptp 12597A-005 paper tape punch interface - tty 12531C buffered teleprinter interface - clk 12539C time base generator + ptr 12597A-002 paper tape reader interface + ptp 12597A-005 paper tape punch interface + tty 12531C buffered teleprinter interface + clk 12539C time base generator - 13-Sep-04 JDB Added paper tape loop mode, DIAG/READER modifiers to PTR - Added PV_LEFT to PTR TRLLIM register - Modified CLK to permit disable - 15-Aug-04 RMS Added tab to control char set (from Dave Bryan) - 14-Jul-04 RMS Generalized handling of control char echoing - (from Dave Bryan) - 26-Apr-04 RMS Fixed SFS x,C and SFC x,C - Fixed SR setting in IBL - Fixed input behavior during typeout for RTE-IV - Suppressed nulls on TTY output for RTE-IV - Implemented DMA SRQ (follows FLG) - 29-Mar-03 RMS Added support for console backpressure - 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 + 13-Sep-04 JDB Added paper tape loop mode, DIAG/READER modifiers to PTR + Added PV_LEFT to PTR TRLLIM register + Modified CLK to permit disable + 15-Aug-04 RMS Added tab to control char set (from Dave Bryan) + 14-Jul-04 RMS Generalized handling of control char echoing + (from Dave Bryan) + 26-Apr-04 RMS Fixed SFS x,C and SFC x,C + Fixed SR setting in IBL + Fixed input behavior during typeout for RTE-IV + Suppressed nulls on TTY output for RTE-IV + Implemented DMA SRQ (follows FLG) + 29-Mar-03 RMS Added support for console backpressure + 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. @@ -85,60 +85,63 @@ #include "hp2100_defs.h" #include -#define CHAR_FLAG(c) (1u << (c)) +#define CHAR_FLAG(c) (1u << (c)) -#define BEL_FLAG CHAR_FLAG('\a') -#define BS_FLAG CHAR_FLAG('\b') -#define LF_FLAG CHAR_FLAG('\n') -#define CR_FLAG CHAR_FLAG('\r') -#define HT_FLAG CHAR_FLAG('\t') +#define BEL_FLAG CHAR_FLAG('\a') +#define BS_FLAG CHAR_FLAG('\b') +#define LF_FLAG CHAR_FLAG('\n') +#define CR_FLAG CHAR_FLAG('\r') +#define HT_FLAG CHAR_FLAG('\t') -#define FULL_SET 0xFFFFFFFF -#define CNTL_SET (BEL_FLAG | BS_FLAG | HT_FLAG | LF_FLAG | CR_FLAG) +#define FULL_SET 0xFFFFFFFF +#define CNTL_SET (BEL_FLAG | BS_FLAG | HT_FLAG | LF_FLAG | CR_FLAG) -#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_V_AUTOLF (UNIT_V_UF + 3) /* auto linefeed */ -#define UNIT_8B (1 << UNIT_V_8B) -#define UNIT_UC (1 << UNIT_V_UC) -#define UNIT_DIAG (1 << UNIT_V_DIAG) -#define UNIT_AUTOLF (1 << UNIT_V_AUTOLF) +#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_V_AUTOLF (UNIT_V_UF + 3) /* auto linefeed */ +#define UNIT_8B (1 << UNIT_V_8B) +#define UNIT_UC (1 << UNIT_V_UC) +#define UNIT_DIAG (1 << UNIT_V_DIAG) +#define UNIT_AUTOLF (1 << UNIT_V_AUTOLF) -#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 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) +#define CLK_V_ERROR 4 /* clock overrun */ +#define CLK_ERROR (1 << CLK_V_ERROR) extern uint32 PC, SR; extern uint32 dev_cmd[2], dev_ctl[2], dev_flg[2], dev_fbf[2], dev_srq[2]; extern UNIT cpu_unit; -int32 ptr_stopioe = 0; /* stop on error */ -int32 ptr_trlcnt = 0; /* trailer counter */ -int32 ptr_trllim = 40; /* trailer to add */ +int32 ptr_stopioe = 0; /* stop on error */ +int32 ptr_trlcnt = 0; /* trailer counter */ +int32 ptr_trllim = 40; /* trailer to add */ int32 ptp_stopioe = 0; int32 ttp_stopioe = 0; -int32 tty_buf = 0; /* tty buffer */ -int32 tty_mode = 0; /* tty mode */ -int32 tty_shin = 0377; /* tty shift in */ -int32 tty_lf = 0; /* lf flag */ -uint32 tty_cntlprt = CNTL_SET; /* tty print flags */ -uint32 tty_cntlset = CNTL_SET; /* tty cntl set */ -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 }; +int32 tty_buf = 0; /* tty buffer */ +int32 tty_mode = 0; /* tty mode */ +int32 tty_shin = 0377; /* tty shift in */ +int32 tty_lf = 0; /* lf flag */ +uint32 tty_cntlprt = CNTL_SET; /* tty print flags */ +uint32 tty_cntlset = CNTL_SET; /* tty cntl set */ +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); @@ -160,225 +163,250 @@ t_stat clk_reset (DEVICE *dptr); int32 clk_delay (int32 flg); t_stat tto_out (int32 c); t_stat ttp_out (int32 c); - + /* PTR data structures - ptr_dev PTR device descriptor - ptr_unit PTR unit descriptor - ptr_mod PTR modifiers - ptr_reg PTR register list + 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, 0, &ptrio }; UNIT ptr_unit = { - UDATA (&ptr_svc, UNIT_SEQ+UNIT_ATTABLE+UNIT_ROABLE, 0), - SERIAL_IN_WAIT }; + 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) }, - { FLDATA (SRQ, ptr_dib.srq, 0) }, - { DRDATA (TRLCTR, ptr_trlcnt, 8), REG_HRO }, - { DRDATA (TRLLIM, ptr_trllim, 8), PV_LEFT }, - { 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 } }; + { 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) }, + { FLDATA (SRQ, ptr_dib.srq, 0) }, + { DRDATA (TRLCTR, ptr_trlcnt, 8), REG_HRO }, + { DRDATA (TRLLIM, ptr_trllim, 8), PV_LEFT }, + { 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[] = { - { UNIT_DIAG, UNIT_DIAG, "diagnostic mode", "DIAG", NULL }, - { UNIT_DIAG, 0, "reader mode", "READER", NULL }, - { MTAB_XTD | MTAB_VDV, 0, "DEVNO", "DEVNO", - &hp_setdev, &hp_showdev, &ptr_dev }, - { 0 } }; + { UNIT_DIAG, UNIT_DIAG, "diagnostic mode", "DIAG", NULL }, + { UNIT_DIAG, 0, "reader mode", "READER", NULL }, + { 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, &ptr_attach, NULL, - &ptr_dib, DEV_DISABLE }; + "PTR", &ptr_unit, ptr_reg, ptr_mod, + 1, 10, 31, 1, 8, 8, + NULL, NULL, &ptr_reset, + &ptr_boot, &ptr_attach, 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 + 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, 0, &ptpio }; UNIT ptp_unit = { - UDATA (&ptp_svc, UNIT_SEQ+UNIT_ATTABLE, 0), SERIAL_OUT_WAIT }; + 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) }, - { FLDATA (SRQ, ptp_dib.srq, 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 } }; + { 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) }, + { FLDATA (SRQ, ptp_dib.srq, 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 } }; + { 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 }; - + "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 + 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 +#define TTI 0 +#define TTO 1 +#define TTP 2 DIB tty_dib = { TTY, 0, 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 } }; + { 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) }, - { ORDATA (SHIN, tty_shin, 8), REG_HRO }, - { 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) }, - { FLDATA (SRQ, tty_dib.srq, 0) }, - { FLDATA (KLFP, tty_lf, 0), REG_HRO }, - { 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 (CNTLPRT, tty_cntlprt, 32), REG_HRO }, - { ORDATA (CNTLSET, tty_cntlset, 32), REG_HIDDEN }, - { ORDATA (DEVNO, tty_dib.devno, 6), REG_HRO }, - { NULL } }; + { ORDATA (BUF, tty_buf, 8) }, + { ORDATA (MODE, tty_mode, 16) }, + { ORDATA (SHIN, tty_shin, 8), REG_HRO }, + { 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) }, + { FLDATA (SRQ, tty_dib.srq, 0) }, + { FLDATA (KLFP, tty_lf, 0), REG_HRO }, + { 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 (CNTLPRT, tty_cntlprt, 32), REG_HRO }, + { ORDATA (CNTLSET, tty_cntlset, 32), REG_HIDDEN }, + { ORDATA (DEVNO, tty_dib.devno, 6), REG_HRO }, + { NULL } + }; MTAB tty_mod[] = { - { UNIT_UC+UNIT_8B, UNIT_UC, "UC", "UC", &tty_set_opt, - NULL, ((void *) (UNIT_UC + UNIT_8B)) }, - { UNIT_UC+UNIT_8B, 0 , "7b", "7B", &tty_set_opt, - NULL, ((void *) (UNIT_UC + UNIT_8B)) }, - { UNIT_UC+UNIT_8B, UNIT_8B, "8b", "8B", &tty_set_opt, - NULL, ((void *) (UNIT_UC + UNIT_8B)) }, - { UNIT_AUTOLF, UNIT_AUTOLF, "autolf", "AUTOLF", &tty_set_opt, - NULL, ((void *) UNIT_AUTOLF) }, - { UNIT_AUTOLF, 0 , NULL, "NOAUTOLF", &tty_set_opt, - NULL, ((void *) UNIT_AUTOLF) }, - { MTAB_XTD | MTAB_VDV, 0, "DEVNO", "DEVNO", - &hp_setdev, &hp_showdev, &tty_dev }, - { 0 } }; + { UNIT_UC+UNIT_8B, UNIT_UC, "UC", "UC", &tty_set_opt, + NULL, ((void *) (UNIT_UC + UNIT_8B)) }, + { UNIT_UC+UNIT_8B, 0 , "7b", "7B", &tty_set_opt, + NULL, ((void *) (UNIT_UC + UNIT_8B)) }, + { UNIT_UC+UNIT_8B, UNIT_8B, "8b", "8B", &tty_set_opt, + NULL, ((void *) (UNIT_UC + UNIT_8B)) }, + { UNIT_AUTOLF, UNIT_AUTOLF, "autolf", "AUTOLF", &tty_set_opt, + NULL, ((void *) UNIT_AUTOLF) }, + { UNIT_AUTOLF, 0 , NULL, "NOAUTOLF", &tty_set_opt, + NULL, ((void *) UNIT_AUTOLF) }, + { 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 }; - + "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 + 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, 0, &clkio }; -UNIT clk_unit = { - UDATA (&clk_svc, 0, 0) }; +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 (SRQ, clk_dib.srq, 0) }, - { FLDATA (ERR, clk_error, CLK_V_ERROR) }, - { BRDATA (TIME, clk_time, 10, 24, 8) }, - { ORDATA (DEVNO, clk_dib.devno, 6), REG_HRO }, - { NULL } }; + { 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 (SRQ, clk_dib.srq, 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 } }; + { 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, DEV_DISABLE }; - -/* Paper tape reader: IOT routine */ + "CLK", &clk_unit, clk_reg, clk_mod, + 1, 0, 0, 0, 0, 0, + NULL, NULL, &clk_reset, + NULL, NULL, NULL, + &clk_dib, DEV_DISABLE + }; + +/* Paper tape reader IO instructions */ 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) { setFSR (dev); } /* STF */ - break; -case ioSFC: /* skip flag clear */ - if (FLG (dev) == 0) PC = (PC + 1) & VAMASK; - break; -case ioSFS: /* skip flag set */ - if (FLG (dev) != 0) PC = (PC + 1) & VAMASK; - break; -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) { clrFSR (dev); } /* H/C option */ +dev = IR & I_DEVMASK; /* get device no */ +switch (inst) { /* case on opcode */ + + case ioFLG: /* flag clear/set */ + if ((IR & I_HC) == 0) { setFSR (dev); } /* STF */ + break; + + case ioSFC: /* skip flag clear */ + if (FLG (dev) == 0) PC = (PC + 1) & VAMASK; + break; + + case ioSFS: /* skip flag set */ + if (FLG (dev) != 0) PC = (PC + 1) & VAMASK; + break; + + 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) { clrFSR (dev); } /* H/C option */ return dat; } @@ -388,31 +416,37 @@ 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); -while ((temp = getc (ptr_unit.fileref)) == EOF) { /* read byte, error? */ - if (feof (ptr_unit.fileref)) { /* end of file? */ - if ((ptr_unit.flags & UNIT_DIAG) && (ptr_unit.pos > 0)) { - rewind (ptr_unit.fileref); /* rewind if loop mode */ - ptr_unit.pos = 0; } - else { - if (ptr_trlcnt >= ptr_trllim) { /* added all trailer? */ - if (ptr_stopioe) { /* stop on error? */ - printf ("PTR end of file\n"); - return SCPE_IOERR; } - else return SCPE_OK; } /* no, just hang */ - ptr_trlcnt++; /* count trailer */ - temp = 0; /* read a zero */ - break; } } - else { /* no, real error */ - perror ("PTR I/O error"); - clearerr (ptr_unit.fileref); - return SCPE_IOERR; } - } -setFSR (dev); /* set flag */ -ptr_unit.buf = temp & 0377; /* put byte in buf */ +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); +while ((temp = getc (ptr_unit.fileref)) == EOF) { /* read byte, error? */ + if (feof (ptr_unit.fileref)) { /* end of file? */ + if ((ptr_unit.flags & UNIT_DIAG) && (ptr_unit.pos > 0)) { + rewind (ptr_unit.fileref); /* rewind if loop mode */ + ptr_unit.pos = 0; + } + else { + if (ptr_trlcnt >= ptr_trllim) { /* added all trailer? */ + if (ptr_stopioe) { /* stop on error? */ + printf ("PTR end of file\n"); + return SCPE_IOERR; + } + else return SCPE_OK; /* no, just hang */ + } + ptr_trlcnt++; /* count trailer */ + temp = 0; /* read a zero */ + break; + } + } + else { /* no, real error */ + perror ("PTR I/O error"); + clearerr (ptr_unit.fileref); + return SCPE_IOERR; + } + } +setFSR (dev); /* set flag */ +ptr_unit.buf = temp & 0377; /* put byte in buf */ ptr_unit.pos = ftell (ptr_unit.fileref); return SCPE_OK; } @@ -429,115 +463,127 @@ return attach_unit (uptr, cptr); t_stat ptr_reset (DEVICE *dptr) { -ptr_dib.cmd = ptr_dib.ctl = 0; /* clear cmd, ctl */ -ptr_dib.flg = ptr_dib.fbf = ptr_dib.srq = 1; /* set flg, fbf, srq */ +ptr_dib.cmd = ptr_dib.ctl = 0; /* clear cmd, ctl */ +ptr_dib.flg = ptr_dib.fbf = ptr_dib.srq = 1; /* set flg, fbf, srq */ ptr_unit.buf = 0; -sim_cancel (&ptr_unit); /* deactivate unit */ +sim_cancel (&ptr_unit); /* deactivate unit */ return SCPE_OK; } /* Paper tape reader bootstrap routine (HP 12992K ROM) */ const uint16 ptr_rom[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 */ - 0103710, /* STC RDR,C ; start reader */ - 0102310, /* SFS RDR ; wait */ - 0027745, /* JMP *-1 */ - 0106410, /* 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 */ + 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 */ + 0103710, /* STC RDR,C ; start reader */ + 0102310, /* SFS RDR ; wait */ + 0027745, /* JMP *-1 */ + 0106410, /* 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 dev; -dev = ptr_dib.devno; /* get device no */ -if (ibl_copy (ptr_rom, dev)) return SCPE_IERR; /* copy boot to memory */ -SR = (SR & IBL_OPT) | IBL_PTR | (dev << IBL_V_DEV); /* set SR */ +dev = ptr_dib.devno; /* get device no */ +if (ibl_copy (ptr_rom, dev)) return SCPE_IERR; /* copy boot to memory */ +SR = (SR & IBL_OPT) | IBL_PTR | (dev << IBL_V_DEV); /* set SR */ return SCPE_OK; } - -/* Paper tape punch: IOT routine */ + +/* Paper tape punch IO instructions */ 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) { setFSR (dev); } /* STF */ - break; -case ioSFC: /* skip flag clear */ - if (FLG (dev) == 0) PC = (PC + 1) & VAMASK; - break; -case ioSFS: /* skip flag set */ - if (FLG (dev) != 0) PC = (PC + 1) & VAMASK; - break; -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) { clrFSR (dev); } /* H/C option */ +dev = IR & I_DEVMASK; /* get device no */ +switch (inst) { /* case on opcode */ + + case ioFLG: /* flag clear/set */ + if ((IR & I_HC) == 0) { setFSR (dev); } /* STF */ + break; + + case ioSFC: /* skip flag clear */ + if (FLG (dev) == 0) PC = (PC + 1) & VAMASK; + break; + + case ioSFS: /* skip flag set */ + if (FLG (dev) != 0) PC = (PC + 1) & VAMASK; + break; + + 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) { clrFSR (dev); } /* H/C option */ return dat; } @@ -547,16 +593,17 @@ t_stat ptp_svc (UNIT *uptr) { int32 dev; -dev = ptp_dib.devno; /* get device no */ -clrCMD (dev); /* clear cmd */ -setFSR (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 */ +dev = ptp_dib.devno; /* get device no */ +clrCMD (dev); /* clear cmd */ +setFSR (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; } @@ -564,51 +611,61 @@ return SCPE_OK; t_stat ptp_reset (DEVICE *dptr) { -ptp_dib.cmd = ptp_dib.ctl = 0; /* clear cmd, ctl */ -ptp_dib.flg = ptp_dib.fbf = ptp_dib.srq = 1; /* set flg, fbf, srq */ +ptp_dib.cmd = ptp_dib.ctl = 0; /* clear cmd, ctl */ +ptp_dib.flg = ptp_dib.fbf = ptp_dib.srq = 1; /* set flg, fbf, srq */ ptp_unit.buf = 0; -sim_cancel (&ptp_unit); /* deactivate unit */ +sim_cancel (&ptp_unit); /* deactivate unit */ return SCPE_OK; } - -/* Terminal: IOT routine */ + +/* Terminal IO instructions */ 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) { setFSR (dev); } /* STF */ - break; -case ioSFC: /* skip flag clear */ - if (FLG (dev) == 0) PC = (PC + 1) & VAMASK; - break; -case ioSFS: /* skip flag set */ - if (FLG (dev) != 0) PC = (PC + 1) & VAMASK; - break; -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) { clrFSR (dev); } /* H/C option */ +dev = IR & I_DEVMASK; /* get device no */ +switch (inst) { /* case on opcode */ + + case ioFLG: /* flag clear/set */ + if ((IR & I_HC) == 0) { setFSR (dev); } /* STF */ + break; + + case ioSFC: /* skip flag clear */ + if (FLG (dev) == 0) PC = (PC + 1) & VAMASK; + break; + + case ioSFS: /* skip flag set */ + if (FLG (dev) != 0) PC = (PC + 1) & VAMASK; + break; + + 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) { clrFSR (dev); } /* H/C option */ return dat; } @@ -641,28 +698,33 @@ 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 */ -tty_shin = 0377; /* assume inactive */ -if (tty_lf) { /* auto lf pending? */ - c = 012; /* force lf */ - tty_lf = 0; } -else { 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); - tty_lf = ((c & 0177) == 015) && (uptr->flags & UNIT_AUTOLF); - } -if (tty_mode & TM_KBD) { /* keyboard enabled? */ - tty_buf = c; /* put char in buf */ - tty_unit[TTI].pos = tty_unit[TTI].pos + 1; - setFSR (dev); /* set flag */ - if (c) { - tto_out (c); /* echo? */ - return ttp_out (c); } } /* punch? */ -else tty_shin = c; /* no, char shifts in */ +dev = tty_dib.devno; /* get device no */ +sim_activate (&tty_unit[TTI], tty_unit[TTI].wait); /* continue poll */ +tty_shin = 0377; /* assume inactive */ +if (tty_lf) { /* auto lf pending? */ + c = 012; /* force lf */ + tty_lf = 0; + } +else { + 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); + tty_lf = ((c & 0177) == 015) && (uptr->flags & UNIT_AUTOLF); + } +if (tty_mode & TM_KBD) { /* keyboard enabled? */ + tty_buf = c; /* put char in buf */ + tty_unit[TTI].pos = tty_unit[TTI].pos + 1; + setFSR (dev); /* set flag */ + if (c) { + tto_out (c); /* echo? */ + return ttp_out (c); /* punch? */ + } + } +else tty_shin = c; /* no, char shifts in */ return SCPE_OK; } @@ -671,43 +733,48 @@ t_stat tto_svc (UNIT *uptr) int32 c, dev; t_stat r; -c = tty_buf; /* get char */ -tty_buf = tty_shin; /* shift in */ -tty_shin = 0377; /* line inactive */ -if ((r = tto_out (c)) != SCPE_OK) { /* output; error? */ - sim_activate (uptr, uptr->wait); /* retry */ - return ((r == SCPE_STALL)? SCPE_OK: r); } /* !stall? report */ -dev = tty_dib.devno; /* get device no */ -setFSR (dev); /* set done flag */ -return ttp_out (c); /* punch if enabled */ +c = tty_buf; /* get char */ +tty_buf = tty_shin; /* shift in */ +tty_shin = 0377; /* line inactive */ +if ((r = tto_out (c)) != SCPE_OK) { /* output; error? */ + sim_activate (uptr, uptr->wait); /* retry */ + return ((r == SCPE_STALL)? SCPE_OK: r); /* !stall? report */ + } +dev = tty_dib.devno; /* get device no */ +setFSR (dev); /* set done flag */ +return ttp_out (c); /* punch if enabled */ } t_stat tto_out (int32 c) { t_stat r; -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); - if ((c > 31) || (CHAR_FLAG (c) & tty_cntlprt)) {/* normal, ctrl? */ - if (r = sim_putchar_s (c)) return r; /* output char */ - tty_unit[TTO].pos = tty_unit[TTO].pos + 1; } - } +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); + if ((c > 31) || (CHAR_FLAG (c) & tty_cntlprt)) { /* normal, ctrl? */ + if (r = sim_putchar_s (c)) return r; /* output char */ + tty_unit[TTO].pos = tty_unit[TTO].pos + 1; + } + } return SCPE_OK; } t_stat ttp_out (int32 c) { -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); } +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 SCPE_OK; } @@ -715,14 +782,14 @@ return SCPE_OK; t_stat tty_reset (DEVICE *dptr) { -tty_dib.cmd = tty_dib.ctl = 0; /* clear cmd, ctl */ -tty_dib.flg = tty_dib.fbf = tty_dib.srq = 1; /* set flg, fbf, srq */ -tty_mode = TM_KBD; /* enable input */ +tty_dib.cmd = tty_dib.ctl = 0; /* clear cmd, ctl */ +tty_dib.flg = tty_dib.fbf = tty_dib.srq = 1; /* set flg, fbf, srq */ +tty_mode = TM_KBD; /* enable input */ tty_buf = 0; -tty_shin = 0377; /* input inactive */ -tty_lf = 0; /* no lf pending */ -sim_activate (&tty_unit[TTI], tty_unit[TTI].wait); /* activate poll */ -sim_cancel (&tty_unit[TTO]); /* cancel output */ +tty_shin = 0377; /* input inactive */ +tty_lf = 0; /* no lf pending */ +sim_activate (&tty_unit[TTI], tty_unit[TTI].wait); /* activate poll */ +sim_cancel (&tty_unit[TTO]); /* cancel output */ return SCPE_OK; } @@ -738,50 +805,63 @@ if (val == UNIT_8B) tty_cntlprt = FULL_SET; else tty_cntlprt = tty_cntlset; return SCPE_OK; } - -/* Clock: IOT routine */ + +/* Clock IO instructions */ 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) { setFSR (dev); } /* STF */ - break; -case ioSFC: /* skip flag clear */ - if (FLG (dev) == 0) PC = (PC + 1) & VAMASK; - break; -case ioSFS: /* skip flag set */ - if (FLG (dev) != 0) PC = (PC + 1) & VAMASK; - break; -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) { clrFSR (dev); } /* H/C option */ +dev = IR & I_DEVMASK; /* get device no */ +switch (inst) { /* case on opcode */ + + case ioFLG: /* flag clear/set */ + if ((IR & I_HC) == 0) { setFSR (dev); } /* STF */ + break; + + case ioSFC: /* skip flag clear */ + if (FLG (dev) == 0) PC = (PC + 1) & VAMASK; + break; + + case ioSFS: /* skip flag set */ + if (FLG (dev) != 0) PC = (PC + 1) & VAMASK; + break; + + 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) { clrFSR (dev); } /* H/C option */ return dat; } @@ -791,18 +871,19 @@ 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 { setFSR (dev); } /* else set flag */ - clk_ctr = clk_delay (1); } /* reset counter */ +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 { setFSR (dev); } /* else set flag */ + clk_ctr = clk_delay (1); /* reset counter */ + } return SCPE_OK; } @@ -810,12 +891,12 @@ return SCPE_OK; t_stat clk_reset (DEVICE *dptr) { -clk_dib.cmd = clk_dib.ctl = 0; /* clear cmd, ctl */ -clk_dib.flg = clk_dib.fbf = clk_dib.srq = 1; /* set flg, fbf, srq */ -clk_error = 0; /* clear error */ -clk_select = 0; /* clear select */ -clk_ctr = 0; /* clear counter */ -sim_cancel (&clk_unit); /* deactivate unit */ +clk_dib.cmd = clk_dib.ctl = 0; /* clear cmd, ctl */ +clk_dib.flg = clk_dib.fbf = clk_dib.srq = 1; /* set flg, fbf, srq */ +clk_error = 0; /* clear error */ +clk_select = 0; /* clear select */ +clk_ctr = 0; /* clear counter */ +sim_cancel (&clk_unit); /* deactivate unit */ return SCPE_OK; } diff --git a/HP2100/hp2100_sys.c b/HP2100/hp2100_sys.c index 3ab12a1f..3f331659 100644 --- a/HP2100/hp2100_sys.c +++ b/HP2100/hp2100_sys.c @@ -1,6 +1,6 @@ /* hp2100_sys.c: HP 2100 simulator interface - Copyright (c) 1993-2004, Robert M. Supnik + Copyright (c) 1993-2005, 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"), @@ -19,26 +19,26 @@ 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 + 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-Nov-04 JDB Added STOP_OFFLINE, STOP_PWROFF messages - 25-Sep-04 JDB Added memory protect device - Fixed display of CCA/CCB/CCE instructions - 01-Jun-04 RMS Added latent 13037 support - 19-Apr-04 RMS Recognize SFS x,C and SFC x,C - 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 + 19-Nov-04 JDB Added STOP_OFFLINE, STOP_PWROFF messages + 25-Sep-04 JDB Added memory protect device + Fixed display of CCA/CCB/CCE instructions + 01-Jun-04 RMS Added latent 13037 support + 19-Apr-04 RMS Recognize SFS x,C and SFC x,C + 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" @@ -64,12 +64,12 @@ 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 + 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"; @@ -81,49 +81,51 @@ REG *sim_PC = &cpu_reg[0]; int32 sim_emax = 3; DEVICE *sim_devices[] = { - &cpu_dev, - &mp_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, - &ds_dev, - &mtd_dev, &mtc_dev, - &msd_dev, &msc_dev, - &muxl_dev, &muxu_dev, &muxc_dev, - &ipli_dev, &iplo_dev, - NULL }; + &cpu_dev, + &mp_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, + &ds_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_msg, - "Breakpoint", - "Indirect address loop", - "Indirect address interrupt (should not happen!)", - "No connection on interprocessor link", - "Device/unit offline", - "Device/unit powered off" }; - + "Unknown error", + "Unimplemented instruction", + "Non-existent I/O device", + halt_msg, + "Breakpoint", + "Indirect address loop", + "Indirect address interrupt (should not happen!)", + "No connection on interprocessor link", + "Device/unit offline", + "Device/unit powered off" + }; + /* 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 + count'xxx + origin + word 0 + : + word count-1 + checksum The checksum includes the origin but not the count. */ @@ -142,53 +144,56 @@ 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; +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; + } } - + /* 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) +#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 }; + 0177777, 0177777 + }; static const char *opcode[] = { "NOP", "NOP", "AND", "JSB", @@ -229,9 +234,10 @@ static const char *opcode[] = { "SBT", "MBT", "CBT", "SBT", "ISY", "DSY", "JPY", "SBS", "CBS", "TBS", "CMW", "MVW", - NULL, /* decode only */ - NULL }; - + 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, @@ -271,8 +277,9 @@ static const int32 opc_val[] = { 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 }; + 0000000+I_ASH, /* decode only */ + -1 + }; /* Decode tables for shift and alter/skip groups */ @@ -285,7 +292,8 @@ static const char *stab[] = { "ALS", "ARS", "RAL", "RAR", "ALR", "ERA", "ELA", "ALF", "BLS", "BRS", "RBL", "RBR", "BLR", "ERB", "ELB", "BLF", "INA", "INB", "SZA", "SZB", "RSS", - NULL }; + NULL + }; static const int32 mtab[] = { 0007700, 0007700, 0007700, 0007700, 0007700, 0007700, 0007700, 0007700, @@ -296,7 +304,8 @@ static const int32 mtab[] = { 0006027, 0006027, 0006027, 0006027, 0006027, 0006027, 0006027, 0006027, 0006027, 0006027, 0006027, 0006027, 0006027, 0006027, 0006027, 0006027, 0006004, 0006004, 0006002, 0006002, 0002001, - 0 }; + 0 + }; static const int32 vtab[] = { 0001000, 0001100, 0001200, 0001300, 0001400, 0001500, 0001600, 0001700, @@ -307,110 +316,125 @@ static const int32 vtab[] = { 0000020, 0000021, 0000022, 0000023, 0000024, 0000025, 0000026, 0000027, 0004020, 0004021, 0004022, 0004023, 0004024, 0004025, 0004026, 0004027, 0002004, 0006004, 0002002, 0006002, 0002001, - -1 }; - + -1 + }; + /* Symbolic decode Inputs: - *of = output stream - addr = current PC - *val = pointer to data - *uptr = pointer to unit - sw = switches + *of = output stream + addr = current PC + *val = pointer to data + *uptr = pointer to unit + sw = switches Outputs: - return = status code + 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) + 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 ('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? */ +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 */ - 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 */ + 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 + *cptr = pointer to input string Outputs: - val = address - -1 if error + val = address + -1 if error */ int32 get_addr (char *cptr) @@ -419,27 +443,28 @@ 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 */ +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; } +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 + *iptr = pointer to input string + addr = current PC + *uptr = pointer to unit + *val = pointer to output values + sw = switches Outputs: - status = error status + status = error status */ t_stat parse_sym (char *iptr, t_addr addr, UNIT *uptr, t_value *val, int32 sw) @@ -449,96 +474,110 @@ t_stat r, ret; char *cptr, gbuf[CBUFSIZE]; cflag = (uptr == NULL) || (uptr == &cpu_unit); -while (isspace (*iptr)) iptr++; /* absorb spaces */ +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 (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 */ + 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; + } ret = SCPE_OK; -cptr = get_glyph (iptr, gbuf, 0); /* get opcode */ +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 */ +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 */ - 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 @@ -570,24 +609,29 @@ 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 */ + 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 index 3945c36f..2387edfc 100644 --- a/I1401/i1401_cd.c +++ b/I1401/i1401_cd.c @@ -1,6 +1,6 @@ /* i1401_cd.c: IBM 1402 card reader/punch - Copyright (c) 1993-2004, Robert M. Supnik + Copyright (c) 1993-2005, 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"), @@ -19,28 +19,30 @@ 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 + 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 + 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. - 14-Nov-04 WVS Added column binary support - 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 + 30-Aug-05 RMS Fixed read, punch to ignore modifier on 1,4 char inst + (reported by Van Snyder) + 14-Nov-04 WVS Added column binary support + 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" @@ -52,88 +54,97 @@ extern char bcd_to_ascii[64]; extern char ascii_to_bcd[128]; extern int16 colbin[64]; int32 s1sel, s2sel, s4sel, s8sel; -char rbuf[2 * CBUFSIZE]; /* > CDR_WIDTH */ +char rbuf[2 * 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 + 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 }; + 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 } }; + { 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 }; + "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 + 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) }; + 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 } }; + { 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 }; + "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 + 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) } }; + { 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 } }; + { 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 }; - + "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 @@ -142,55 +153,58 @@ DEVICE stack_dev = { t_stat read_card (int32 ilnt, int32 mod) { -int32 i, j; +int32 i, j, cbn; int16 c; 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 (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 < 2 * CBUFSIZE; i++) rbuf[i] = 0; /* clear extended buf */ -fgets (rbuf, (mod == BCD_C)? 2 * CBUFSIZE: CBUFSIZE, /* rd bin/char card */ - cdr_unit.fileref); -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); } -if (mod == BCD_C) { /* column binary */ - for (i = 0; i < 2 * CDR_WIDTH; i++) /* cvt to BCD */ - rbuf[i] = ascii_to_bcd[rbuf[i]]; - for (i = 0; i < CDR_WIDTH; i++) { - M[CD_CBUF1 + i] = (M[CD_CBUF1 + i] & WM) | rbuf[i]; - M[CD_CBUF2 + i] = (M[CD_CBUF2 + i] & WM) | rbuf[CDR_WIDTH + i]; - c = (rbuf[i] << 6) | rbuf[CDR_WIDTH + i]; - M[CDR_BUF + i] = (M[CDR_BUF + i] & WM) | 077; - for (j = 0; j < 64; j++) { /* look for char */ - if (c == colbin[j]) { - M[CDR_BUF + i] = (M[CDR_BUF + i] & WM) | j; - break; - } /* end if */ - } /* end for j */ - } /* end for i */ - } /* end if col bin */ -else { /* normal read */ - 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 */ +ind[IN_READ] = ind[IN_LST] = s1sel = s2sel = 0; /* default stacker */ +cbn = ((ilnt == 2) || (ilnt == 5)) && (mod == BCD_C); /* col binary? */ +for (i = 0; i < 2 * CBUFSIZE; i++) rbuf[i] = 0; /* clear extended buf */ +fgets (rbuf, (cbn)? 2 * CBUFSIZE: CBUFSIZE, /* rd bin/char card */ + cdr_unit.fileref); +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); + } +if (cbn) { /* column binary */ + for (i = 0; i < 2 * CDR_WIDTH; i++) /* cvt to BCD */ + rbuf[i] = ascii_to_bcd[rbuf[i]]; + for (i = 0; i < CDR_WIDTH; i++) { + M[CD_CBUF1 + i] = (M[CD_CBUF1 + i] & WM) | rbuf[i]; + M[CD_CBUF2 + i] = (M[CD_CBUF2 + i] & WM) | rbuf[CDR_WIDTH + i]; + c = (rbuf[i] << 6) | rbuf[CDR_WIDTH + i]; + M[CDR_BUF + i] = (M[CDR_BUF + i] & WM) | 077; + for (j = 0; j < 64; j++) { /* look for char */ + if (c == colbin[j]) { + M[CDR_BUF + i] = (M[CDR_BUF + i] & WM) | j; + break; + } /* end if */ + } /* end for j */ + } /* end for i */ + } /* end if col bin */ +else { /* normal read */ + 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; } @@ -203,23 +217,24 @@ 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? */ +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 */ +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 @@ -228,44 +243,46 @@ return SCPE_OK; t_stat punch_card (int32 ilnt, int32 mod) { -int32 i; -static char pbuf[(2 * CDP_WIDTH) + 1]; /* + null */ +int32 i, cbn; +static char pbuf[(2 * 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 */ +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 */ +cbn = ((ilnt == 2) || (ilnt == 5)) && (mod == BCD_C); /* col binary? */ -M[CDP_BUF - 1] = 012; /* set prev loc */ -if (mod == BCD_C) { /* column binary */ - for (i = 0; i < CDP_WIDTH; i++) { - pbuf[i] = bcd_to_ascii[M[CD_CBUF1 + i] & CHAR]; - pbuf[i + CDP_WIDTH] = bcd_to_ascii[M[CD_CBUF2 + i] & CHAR]; - } - for (i = 2 * CDP_WIDTH - 1; (i >= 0) && (pbuf[i] == ' '); i--) - pbuf[i] = 0; - pbuf[2 * CDP_WIDTH] = 0; /* trailing null */ - } -else { /* normal */ - 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 */ +M[CDP_BUF - 1] = 012; /* set prev loc */ +if (cbn) { /* column binary */ + for (i = 0; i < CDP_WIDTH; i++) { + pbuf[i] = bcd_to_ascii[M[CD_CBUF1 + i] & CHAR]; + pbuf[i + CDP_WIDTH] = bcd_to_ascii[M[CD_CBUF2 + i] & CHAR]; + } + for (i = 2 * CDP_WIDTH - 1; (i >= 0) && (pbuf[i] == ' '); i--) + pbuf[i] = 0; + pbuf[2 * CDP_WIDTH] = 0; /* trailing null */ + } +else { /* normal */ + 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 @@ -285,9 +302,9 @@ return SCPE_OK; 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 */ +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; } @@ -295,7 +312,7 @@ return SCPE_OK; t_stat cdr_attach (UNIT *uptr, char *cptr) { -ind[IN_LST] = ind[IN_READ] = 0; /* clear last card */ +ind[IN_LST] = ind[IN_READ] = 0; /* clear last card */ return attach_unit (uptr, cptr); } @@ -305,14 +322,15 @@ return attach_unit (uptr, cptr); #define BOOT_LEN (sizeof (boot_rom) / sizeof (unsigned char)) static const unsigned char boot_rom[] = { - OP_R + WM, OP_NOP + WM }; /* R, NOP */ + 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 < 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 index 8dabfeb8..c8702a6d 100644 --- a/I1401/i1401_cpu.c +++ b/I1401/i1401_cpu.c @@ -1,6 +1,6 @@ /* i1401_cpu.c: IBM 1401 CPU simulator - Copyright (c) 1993-2004, Robert M. Supnik + Copyright (c) 1993-2005, 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"), @@ -19,41 +19,45 @@ 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 + 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. - 14-Nov-04 WVS Added column binary support, debug support - 06-Nov-04 RMS Added instruction history - 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 + 01-Sep-05 RMS Removed error stops in MCE + 16-Aug-05 RMS Fixed C++ declaration and cast problems + 02-Jun-05 RMS Fixed SSB-SSG clearing on RESET + (reported by Ralph Reinke) + 14-Nov-04 WVS Added column binary support, debug support + 06-Nov-04 RMS Added instruction history + 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 + 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 @@ -71,10 +75,10 @@ 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 + 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 @@ -82,18 +86,17 @@ 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 + 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. + + 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. @@ -102,10 +105,10 @@ 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 + HALT instruction + breakpoint encountered + illegal addresses or instruction formats + I/O error in I/O simulator 2. Interrupts. The 1401 has no interrupt structure. @@ -114,72 +117,77 @@ 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 + 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 +#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 -#define HIST_MIN 64 -#define HIST_MAX 65536 -struct InstHistory { - uint16 is; - uint16 ilnt; - uint8 inst[MAX_L]; }; +#define HIST_MIN 64 +#define HIST_MAX 65536 + +typedef struct { + uint16 is; + uint16 ilnt; + uint8 inst[MAX_L]; + } InstHistory; /* 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 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; +#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 */ -int32 hst_p = 0; /* history pointer */ -int32 hst_lnt = 0; /* history length */ -struct InstHistory *hst = NULL; /* instruction history */ +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 */ +int32 hst_p = 0; /* history pointer */ +int32 hst_lnt = 0; /* history length */ +InstHistory *hst = NULL; /* instruction history */ extern int32 sim_int_char; extern int32 sim_emax; extern t_value *sim_eval; extern FILE *sim_deb; -extern int32 sim_brk_types, sim_brk_dflt, sim_brk_summ; /* breakpoint info */ +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); @@ -207,145 +215,150 @@ 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); 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 modifier list + 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) }; +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 } }; + { 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 }, - { MTAB_XTD|MTAB_VDV|MTAB_NMO|MTAB_SHP, 0, "HISTORY", "HISTORY", - &cpu_set_hist, &cpu_show_hist }, - { 0 } }; + { 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 }, + { MTAB_XTD|MTAB_VDV|MTAB_NMO|MTAB_SHP, 0, "HISTORY", "HISTORY", + &cpu_set_hist, &cpu_show_hist }, + { 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, - NULL, DEV_DEBUG }; - + "CPU", &cpu_unit, cpu_reg, cpu_mod, + 1, 10, 14, 1, 8, 7, + &cpu_ex, &cpu_dep, &cpu_reset, + NULL, NULL, NULL, + NULL, DEV_DEBUG + }; + /* 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 */ + 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 }; @@ -353,103 +366,112 @@ const int32 len_table[9] = { 0, L1, L2, 0, L4, L5, 0, L7, L8 }; 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 }; + 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 }; + 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 }; + 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 }; + 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 }; + 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 */ + 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 }; + 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 }; + 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 }; + 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 */ @@ -458,7 +480,7 @@ static const int32 p_mod[] = { BCD_C, -1 }; 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; @@ -472,30 +494,32 @@ t_stat reason, r1, r2; /* Restore saved state */ - IS = saved_IS; -if (as_err) AS = AS | BA; /* flag bad addresses */ +if (as_err) AS = AS | BA; /* flag bad addresses */ if (bs_err) BS = BS | BA; -as_err = bs_err = 0; /* reset error flags */ +as_err = bs_err = 0; /* reset error flags */ reason = 0; - + /* Main instruction fetch/decode loop */ -while (reason == 0) { /* loop until halted */ +while (reason == 0) { /* loop until halted */ -if (hb_pend) { /* halt br pending? */ - hb_pend = 0; /* clear flag */ - BRANCH; } /* execute branch */ + 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; } + 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; } + if (sim_brk_summ && sim_brk_test (IS, SWMASK ('E'))) { /* breakpoint? */ + reason = STOP_IBKPT; /* stop simulation */ + break; + } -sim_interval = sim_interval - 1; + sim_interval = sim_interval - 1; /* Instruction fetch - 1401 fetch works as follows: @@ -515,635 +539,689 @@ sim_interval = sim_interval - 1; 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. + The 1401 does not 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 ((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) 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-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) { /* 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) goto CHECK_LENGTH; /* I-4: WM? 4 char inst */ + if ((op == OP_B) && (t == BCD_BLANK)) /* BR + space? */ + goto CHECK_LENGTH; + 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-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 ((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); } + 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); + } + if (reason) break; /* addr err on last? */ CHECK_LENGTH: -if ((flags & BREQ) && ADDR_ERR (BS)) { /* valid B? */ - reason = STOP_INVB; - break; } -if ((flags & AREQ) && ADDR_ERR (AS)) { /* valid A? */ - reason = STOP_INVA; - break; } -ilnt = IS - saved_IS; /* get lnt */ -if (hst_lnt) { /* history enabled? */ - hst_p = (hst_p + 1); /* next entry */ - if (hst_p >= hst_lnt) hst_p = 0; - hst[hst_p].is = saved_IS; /* save IS */ - hst[hst_p].ilnt = ilnt; - for (i = 0; (i < MAX_L) && (i < ilnt); i++) - hst[hst_p].inst[i] = M[saved_IS + i]; - } -if (DEBUG_PRS (cpu_dev)) { - fprint_val (sim_deb, saved_IS, 10, 5, PV_RSPC); - fprintf (sim_deb, ": " ); - for (i = 0; i < sim_emax; i++) sim_eval[i] = 0; - for (i = 0, k = saved_IS; i < sim_emax; i++, k++) { - if (cpu_ex (&sim_eval[i], k, &cpu_unit, 0) != SCPE_OK) break; } - fprint_sym (sim_deb, saved_IS, sim_eval, &cpu_unit, SWMASK('M')); - fprintf (sim_deb, "\n" ); - } -switch (op) { /* case on opcode */ - -/* Move/load character instructions A check B check + if ((flags & BREQ) && ADDR_ERR (BS)) { /* valid B? */ + reason = STOP_INVB; + break; + } + if ((flags & AREQ) && ADDR_ERR (AS)) { /* valid A? */ + reason = STOP_INVA; + break; + } + ilnt = IS - saved_IS; /* get lnt */ + if (hst_lnt) { /* history enabled? */ + hst_p = (hst_p + 1); /* next entry */ + if (hst_p >= hst_lnt) hst_p = 0; + hst[hst_p].is = saved_IS; /* save IS */ + hst[hst_p].ilnt = ilnt; + for (i = 0; (i < MAX_L) && (i < ilnt); i++) + hst[hst_p].inst[i] = M[saved_IS + i]; + } + if (DEBUG_PRS (cpu_dev)) { + fprint_val (sim_deb, saved_IS, 10, 5, PV_RSPC); + fprintf (sim_deb, ": " ); + for (i = 0; i < sim_emax; i++) sim_eval[i] = 0; + for (i = 0, k = saved_IS; i < sim_emax; i++, k++) { + if (cpu_ex (&sim_eval[i], k, &cpu_unit, 0) != SCPE_OK) break; + } + fprint_sym (sim_deb, saved_IS, sim_eval, &cpu_unit, SWMASK('M')); + fprintf (sim_deb, "\n" ); + } + switch (op) { /* case on opcode */ - 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 +/* 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 + 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_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); /* decr pointers */ + MM (BS); + } 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 + 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); /* decr pointers */ + MM (BS); + } while ((wm & WM) == 0); /* stop on A WM */ + break; - 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 +/* 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 + 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_MCM: /* move to rec/group */ + do { + t = M[AS]; + M[BS] = (M[BS] & WM) | (M[AS] & CHAR); /* move char */ + PP (AS); /* incr pointers */ + PP (BS); + } 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_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_MN: /* move numeric */ + M[BS] = (M[BS] & ~DIGIT) | (M[AS] & DIGIT); /* move digit */ + MM (AS); /* decr pointers */ + MM (BS); + 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 + case OP_MZ: /* move zone */ + M[BS] = (M[BS] & ~ZONE) | (M[AS] & ZONE); /* move high bits */ + MM (AS); /* decr pointers */ + MM (BS); + 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 + 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; + 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 +/* 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 + 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 + 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_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 + case OP_BBE: /* branch if bit eq */ + if (M[BS] & D & CHAR) { BRANCH; } /* any bits set? */ + else { MM (BS); } /* decr pointer */ + break; - 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 +/* 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 + 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_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_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 + 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; - 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 +/* 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 + 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, r_mod)) 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_R: /* read */ + if (reason = iomod (ilnt, D, r_mod)) 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_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, p_mod)) 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_P: /* punch */ + if (reason = iomod (ilnt, D, p_mod)) 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_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_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_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_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_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; + 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 + 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_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 */ -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 + 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 + 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 + 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 + 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 */ + case OP_MCE: /* edit */ + a = M[AS]; /* get A char */ + b = M[BS]; /* get B char */ + t = a & DIGIT; /* get A digit */ + MM (AS); + 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 + * 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 */ + do { + b = M[BS]; /* get B char */ + M[BS] = M[BS] & ~WM; /* clr WM */ + switch (b & CHAR) { /* case on B char */ - if (reason) break; /* address err? */ - if (!qawm || !qzero) { /* rescan? */ - if (qdollar) reason = STOP_MCE3; /* error if $ */ - break; } + case BCD_ASTER: /* * */ + if (!qbody || qdollar || !(cpu_unit.flags & EPE)) break; + qaster = 1; /* flag */ + goto A_CYCLE; /* take A cycle */ -/* Edit pass 2 - from left to right, supressing zeroes */ + case BCD_DOLLAR: /* $ */ + if (!qbody || qaster || !(cpu_unit.flags & EPE)) break; + qdollar = 1; /* flag */ + goto A_CYCLE; /* take A cycle */ - 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); + case BCD_ZERO: /* 0 */ + if (qawm) { /* left status? */ + if (!qzero) M[BS] = M[BS] | WM; /* first? set WM */ + qzero = 1; /* flag suppress */ + break; + } + if (!qzero) t = t | WM; /* body, first? WM */ + qzero = 1; /* flag suppress */ + goto A_CYCLE; /* take A cycle */ - 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 $ */ + case BCD_BLANK: /* blank */ + if (qawm) break; /* left status? */ + A_CYCLE: + M[BS] = t; /* copy char */ + if (a & WM) { /* end of A field? */ + qbody = 0; /* end body */ + qawm = 1; /* start left status */ + } + else { + qbody = 1; /* in body */ + a = M[AS]; /* next A */ + MM (AS); + t = a & CHAR; /* use A char */ + } + break; + + case BCD_C: case BCD_R: case BCD_MINUS: /* C, R, - */ + if (!qsign && !qbody) M[BS] = BCD_BLANK; /* + & status? blank */ + break; + + case BCD_COMMA: /* , */ + if (!qbody) M[BS] = BCD_BLANK; /* status? blank */ + break; + + case BCD_AMPER: /* & */ + M[BS] = BCD_BLANK; /* blank */ + break; + } /* end switch */ + + MM (BS); /* decr B pointer */ + } while ((b & WM) == 0); /* stop on B WM */ + + if (reason) break; /* address err? */ + if (!qzero) break; /* rescan? */ + +/* Edit pass 2 - from left to right, suppressing 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)) /* flag for EPE */ + qdecimal = 1; + break; + + 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 */ + } 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! */ - + 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 @@ -1159,55 +1237,58 @@ case OP_MCE: /* edit */ 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 + 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); + case OP_MUL: + asave = AS; /* save AS, BS */ + bsave = lowprd = BS; + do { + a = M[AS]; /* get mpcd char */ + M[BS] = BCD_ZERO; /* zero prod */ + MM (AS); /* decr pointers */ + MM (BS); + } 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; - + 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 @@ -1234,205 +1315,215 @@ case OP_MUL: 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 + 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 */ + 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 + + 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? */ + 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 + 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 + div_sign (M[asave], b, qs - 1, bsave - 1); /* set signs */ + BS = qs - 2; /* BS = quo 10's pos */ + break; - SWM set WM on A char and B char fetch fetch - CWM clear WM on A char and B char fetch fetch +/* 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 + 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_SWM: /* set word mark */ + M[BS] = M[BS] | WM; /* set A field mark */ + M[AS] = M[AS] | WM; /* set B field mark */ + MM (AS); /* decr pointers */ + MM (BS); + 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; + 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); /* decr pointers */ + MM (BS); + break; -/* Clear storage instruction A check B check +/* Clear storage instruction A check B check - CS clear from B down to nearest hundreds if branch fetch - address + 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 + 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; + 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 +/* Modify address instruction A check B check - MA add A addr and B addr, store at B addr fetch fetch + 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 + 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; + 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 +/* Store address instructions A-check B-check - SAR store A* at A addr fetch - SBR store B* at A addr fetch + 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 + 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; + 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; + 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; + 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 */ + default: + reason = STOP_NXI; /* unimplemented */ + break; + } /* end switch */ + } /* end while */ /* Simulation halted */ -as_err = ADDR_ERR (AS); /* get addr err flags */ +as_err = ADDR_ERR (AS); /* get addr err flags */ bs_err = ADDR_ERR (BS); -AS = AS & ADDRMASK; /* clean addresses */ +AS = AS & ADDRMASK; /* clean addresses */ BS = BS & ADDRMASK; -pcq_r->qptr = pcq_p; /* update pc q ptr */ +pcq_r->qptr = pcq_p; /* update pc q ptr */ return reason; -} /* end sim_instr */ - +} /* end sim_instr */ + /* store addr_x - convert address to BCD character in x position Inputs: - addr = address to convert + addr = address to convert Outputs: - char = converted address character + char = converted address character */ int32 store_addr_h (int32 addr) @@ -1462,14 +1553,16 @@ 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); +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; } @@ -1479,87 +1572,94 @@ 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 */ +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 */ +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 - */ +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 + 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 + 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); +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 + 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 */ +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 */ +for (i = 0; i < 64; i++) { /* clr indicators */ + if ((i < IN_SSB) || (i > IN_SSG)) ind[i] = 0; /* except SSB-SSG */ + } +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; @@ -1593,10 +1693,10 @@ int32 mc = 0; uint32 i; if ((val <= 0) || (val > MAXMEMSIZE) || ((val % 1000) != 0)) - return SCPE_ARG; + 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; + return SCPE_OK; MEMSIZE = val; for (i = MEMSIZE; i < MAXMEMSIZE; i++) M[i] = 0; if (MEMSIZE > 4000) cpu_unit.flags = cpu_unit.flags | MA; @@ -1612,20 +1712,23 @@ int32 i, lnt; t_stat r; if (cptr == NULL) { - for (i = 0; i < hst_lnt; i++) hst[i].ilnt = 0; - hst_p = 0; - return SCPE_OK; } + for (i = 0; i < hst_lnt; i++) hst[i].ilnt = 0; + hst_p = 0; + return SCPE_OK; + } lnt = (int32) get_uint (cptr, 10, HIST_MAX, &r); if ((r != SCPE_OK) || (lnt && (lnt < HIST_MIN))) return SCPE_ARG; hst_p = 0; if (hst_lnt) { - free (hst); - hst_lnt = 0; - hst = NULL; } + free (hst); + hst_lnt = 0; + hst = NULL; + } if (lnt) { - hst = calloc (sizeof (struct InstHistory), lnt); - if (hst == NULL) return SCPE_MEM; - hst_lnt = lnt; } + hst = (InstHistory *) calloc (lnt, sizeof (InstHistory)); + if (hst == NULL) return SCPE_MEM; + hst_lnt = lnt; + } return SCPE_OK; } @@ -1637,32 +1740,33 @@ int32 i, k, di, lnt; char *cptr = (char *) desc; t_value sim_eval[MAX_L + 1]; t_stat r; -struct InstHistory *h; +InstHistory *h; extern t_stat fprint_sym (FILE *ofile, t_addr addr, t_value *val, - UNIT *uptr, int32 sw); + UNIT *uptr, int32 sw); -if (hst_lnt == 0) return SCPE_NOFNC; /* enabled? */ +if (hst_lnt == 0) return SCPE_NOFNC; /* enabled? */ if (cptr) { - lnt = (int32) get_uint (cptr, 10, hst_lnt, &r); - if ((r != SCPE_OK) || (lnt == 0)) return SCPE_ARG; } + lnt = (int32) get_uint (cptr, 10, hst_lnt, &r); + if ((r != SCPE_OK) || (lnt == 0)) return SCPE_ARG; + } else lnt = hst_lnt; -di = hst_p - lnt; /* work forward */ +di = hst_p - lnt; /* work forward */ if (di < 0) di = di + hst_lnt; fprintf (st, "IS IR\n\n"); -for (k = 0; k < lnt; k++) { /* print specified */ - h = &hst[(++di) % hst_lnt]; /* entry pointer */ - if (h->ilnt) { /* instruction? */ - fprintf (st, "%05d ", h->is); - for (i = 0; i < h->ilnt; i++) - sim_eval[i] = h->inst[i]; - sim_eval[h->ilnt] = WM; - if ((fprint_sym (st, h->is, sim_eval, &cpu_unit, SWMASK ('M'))) > 0) { - fprintf (st, "(undefined)"); - for (i = 0; i < h->ilnt; i++) - fprintf (st, "% 02o", h->inst[i]); - } - fputc ('\n', st); /* end line */ - } /* end else instruction */ - } /* end for */ +for (k = 0; k < lnt; k++) { /* print specified */ + h = &hst[(++di) % hst_lnt]; /* entry pointer */ + if (h->ilnt) { /* instruction? */ + fprintf (st, "%05d ", h->is); + for (i = 0; i < h->ilnt; i++) + sim_eval[i] = h->inst[i]; + sim_eval[h->ilnt] = WM; + if ((fprint_sym (st, h->is, sim_eval, &cpu_unit, SWMASK ('M'))) > 0) { + fprintf (st, "(undefined)"); + for (i = 0; i < h->ilnt; i++) + fprintf (st, "% 02o", h->inst[i]); + } + fputc ('\n', st); /* end line */ + } /* end else instruction */ + } /* end for */ return SCPE_OK; } diff --git a/I1401/i1401_dat.h b/I1401/i1401_dat.h index 93edb695..cc7e2fd6 100644 --- a/I1401/i1401_dat.h +++ b/I1401/i1401_dat.h @@ -1,6 +1,6 @@ /* i1401_dat.h: IBM 1401 character conversion tables - Copyright (c) 1993-2004, Robert M. Supnik + Copyright (c) 1993-2005, 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"), @@ -19,53 +19,55 @@ 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 + 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 }; + 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', '?', '.', ')', '[', '<', '"' }; + ' ', '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', '?', '.', ')', '[', '<', '"' + }; /* Column binary codes for valid punch combinations High-order six bits are rows 12-3, low-order six bits are rows 4-9 */ int16 colbin[64] = { - 00000, 00400, 00200, 00100, 00040, 00020, 00010, 00004, - 00002, 00001, 01000, 00102, 00042, 00022, 00012, 00006, - 07777, 01400, 01200, 01100, 01040, 01020, 01010, 01004, - 01002, 01001, 01202, 01102, 01042, 01022, 01012, 01006, - 02000, 02400, 02200, 02100, 02040, 02020, 02010, 02004, - 02002, 02001, 03000, 02102, 02042, 02022, 02012, 02006, - 04000, 04400, 04200, 04100, 04040, 04020, 04010, 04004, - 04002, 04001, 05000, 04102, 04042, 04022, 04012, 04006 }; + 00000, 00400, 00200, 00100, 00040, 00020, 00010, 00004, + 00002, 00001, 01000, 00102, 00042, 00022, 00012, 00006, + 07777, 01400, 01200, 01100, 01040, 01020, 01010, 01004, + 01002, 01001, 01202, 01102, 01042, 01022, 01012, 01006, + 02000, 02400, 02200, 02100, 02040, 02020, 02010, 02004, + 02002, 02001, 03000, 02102, 02042, 02022, 02012, 02006, + 04000, 04400, 04200, 04100, 04040, 04020, 04010, 04004, + 04002, 04001, 05000, 04102, 04042, 04022, 04012, 04006 + }; diff --git a/I1401/i1401_defs.h b/I1401/i1401_defs.h index 9d169d8d..a7d68c14 100644 --- a/I1401/i1401_defs.h +++ b/I1401/i1401_defs.h @@ -1,6 +1,6 @@ /* i1401_defs.h: IBM 1401 simulator definitions - Copyright (c) 1993-2004, Robert M. Supnik + Copyright (c) 1993-2005, 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"), @@ -19,15 +19,15 @@ 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 + 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. - 14-Nov-04 RMS Added column binary support - 27-Oct-04 RMS Added maximum instruction length - 16-Mar-03 RMS Fixed mnemonic for MCS - 03-Jun-02 RMS Added 1311 support - 14-Apr-99 RMS Converted t_addr to unsigned + 14-Nov-04 RMS Added column binary support + 27-Oct-04 RMS Added maximum instruction length + 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 @@ -35,249 +35,251 @@ in answering questions, gathering source material, and debugging. */ +#ifndef _I1401_DEFS_H_ +#define _I1401_DEFS_H_ 0 + #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 */ +#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_IOC 18 /* I/O check */ +#define STOP_INVDSC 19 /* invalid disk sector */ +#define STOP_INVDCN 20 /* invalid disk count */ +#define STOP_INVDSK 21 /* invalid disk unit */ +#define STOP_INVDFN 22 /* invalid disk func */ +#define STOP_INVDLN 23 /* invalid disk reclen */ +#define STOP_WRADIS 24 /* write address dis */ +#define STOP_WRCHKE 25 /* write check error */ +#define STOP_INVDAD 26 /* invalid disk addr */ +#define STOP_INVDCY 27 /* 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 CD_CBUF1 401 /* r/p col bin buf 12-3 */ -#define CD_CBUF2 501 /* r/p col bin buf 4-9 */ -#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) - +#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 CD_CBUF1 401 /* r/p col bin buf 12-3 */ +#define CD_CBUF2 501 /* r/p col bin buf 4-9 */ +#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 + <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 */ +#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 */ -#define MAX_L 8 /* max length */ +#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 */ +#define MAX_L 8 /* max length */ /* 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) +#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 */ +#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 + 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 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 +#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 - +#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 */ - +#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 */ +#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 */ +#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 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) +#define CRETIOE(f,c) return ((f)? (c): SCPE_OK) + +#endif diff --git a/I1401/i1401_doc.txt b/I1401/i1401_doc.txt index 3e963afa..9a7265e4 100644 --- a/I1401/i1401_doc.txt +++ b/I1401/i1401_doc.txt @@ -1,14 +1,14 @@ To: Users From: Bob Supnik Subj: IBM 1401 Simulator Usage -Date: 15-Nov-2004 +Date: 01-Sep-05 COPYRIGHT NOTICE The following copyright notice applies to both the SIMH source and binary: - Original code published in 1993-2004, written by Robert M Supnik - Copyright (c) 1993-2004, Robert M Supnik + Original code published in 1993-2005, written by Robert M Supnik + Copyright (c) 1993-2005, 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"), @@ -27,8 +27,8 @@ The following copyright notice applies to both the SIMH source and binary: 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 + 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. @@ -95,9 +95,6 @@ any kind of error the simulator stops: 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 diff --git a/I1401/i1401_dp.c b/I1401/i1401_dp.c index 5d53300a..cb80dd86 100644 --- a/I1401/i1401_dp.c +++ b/I1401/i1401_dp.c @@ -1,6 +1,6 @@ /* i1401_dp.c: IBM 1311 disk simulator - Copyright (c) 2002-2004, Robert M. Supnik + Copyright (c) 2002-2005, 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"), @@ -19,21 +19,21 @@ 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 + 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 + 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 + 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 + 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 @@ -48,58 +48,58 @@ #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) +#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_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) +#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 +#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 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 */ +#define CYL u3 /* current cylinder */ -extern uint8 M[]; /* memory */ +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 */ +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); @@ -115,59 +115,63 @@ 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 + 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) } }; + { 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 } }; + { 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 } }; + { 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 }; - + "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 + fnc = function character + flg = load vs move mode + mod = modifier character Outputs: - status = status + status = status */ t_stat dp_io (int32 fnc, int32 flg, int32 mod) @@ -176,177 +180,197 @@ 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 */ +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 */ +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); } +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! */ +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! */ +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? */ +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 */ +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 */ -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 */ +switch (fnc) { /* case on function */ -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_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_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 */ + 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 */ -default: /* unknown */ - return STOP_INVDFN; } + 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 */ -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 */ + 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} ; +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; } +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; } @@ -355,23 +379,27 @@ return SCPE_OK; 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 */ +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; } +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; } @@ -380,19 +408,21 @@ return SCPE_OK; 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 */ +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; } +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; } @@ -401,42 +431,45 @@ return SCPE_OK; 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 */ +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; } +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 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 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 */ +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; } @@ -444,14 +477,15 @@ return -1; 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 */ +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 */ +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; } @@ -461,9 +495,10 @@ 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 */ +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 */ @@ -473,11 +508,12 @@ 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 */ +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 */ @@ -487,7 +523,7 @@ 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)); + (ctrk * DP_NUMSC)); } /* Convert DCF BCD field to binary */ @@ -497,11 +533,12 @@ 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 */ +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; } @@ -511,21 +548,22 @@ 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; } +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 */ +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; } @@ -533,10 +571,11 @@ return cnt; 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++; } +while (cnt-- > 0) { /* fill with blanks */ + *(((uint8 *) uptr->filebuf) + da) = BCD_BLANK; + if (da >= uptr->hwmark) uptr->hwmark = da + 1; + da++; + } return; } @@ -546,10 +585,10 @@ 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 */ +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 */ +sim_cancel (&dp_unit[0]); /* cancel timer */ return SCPE_OK; } diff --git a/I1401/i1401_iq.c b/I1401/i1401_iq.c index e5428b44..98484b63 100644 --- a/I1401/i1401_iq.c +++ b/I1401/i1401_iq.c @@ -1,6 +1,6 @@ /* i1401_iq.c: IBM 1407 inquiry terminal - Copyright (c) 1993-2004, Robert M. Supnik + Copyright (c) 1993-2005, 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"), @@ -19,15 +19,15 @@ 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 + 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 + 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 + 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" @@ -39,7 +39,7 @@ 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 */ +int32 inq_char = 033; /* request inq */ t_stat inq_svc (UNIT *uptr); t_stat inq_reset (DEVICE *dptr); @@ -47,26 +47,28 @@ void puts_tty (char *cptr); /* INQ data structures - inq_dev INQ device descriptor - inq_unit INQ unit descriptor - inq_reg INQ register list + 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 } }; + { 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 }; - + "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 @@ -76,63 +78,78 @@ 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 */ +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; + break; + + 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"); + break; + + default: /* invalid mod */ + return STOP_INVM; + } + +return SCPE_OK; } - + /* 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 */ +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; } @@ -149,7 +166,7 @@ return; t_stat inq_reset (DEVICE *dptr) { -ind[IN_INR] = ind[IN_INC] = 0; /* clear indicators */ -sim_activate (&inq_unit, inq_unit.wait); /* activate poll */ +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 index 4aa68b1c..087c82ba 100644 --- a/I1401/i1401_lp.c +++ b/I1401/i1401_lp.c @@ -19,16 +19,16 @@ 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 + 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 + lpt 1403 line printer - 07-Mar-05 RMS Fixed bug in write_line (reported by Van Snyder) - 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 + 07-Mar-05 RMS Fixed bug in write_line (reported by Van Snyder) + 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" @@ -45,156 +45,180 @@ 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 }; + ' ', '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))) -#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 + 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) }; + 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 } }; + { 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 } }; + { 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 }; - + "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 + 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 */ +static char lbuf[LPT_WIDTH + 1]; /* + null */ -if ((lpt_unit.flags & UNIT_ATT) == 0) return SCPE_UNATT; /* attached? */ +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 */ -lbuf[LPT_WIDTH] = 0; /* trailing null */ +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 */ + } +lbuf[LPT_WIDTH] = 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; } +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 + <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 */ +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 */ + + 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) + count = number of lines to space or skip + sflag = skip (TRUE) or space (FALSE) */ t_stat space (int32 count, int32 sflag) @@ -202,13 +226,14 @@ 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 */ +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; } @@ -217,8 +242,8 @@ return SCPE_OK; t_stat lpt_reset (DEVICE *dptr) { -cctptr = 0; /* clear cct ptr */ -lines = lflag = 0; /* no cc action */ +cctptr = 0; /* clear cct ptr */ +lines = lflag = 0; /* no cc action */ ind[IN_LPT] = 0; return SCPE_OK; } @@ -227,8 +252,8 @@ return SCPE_OK; t_stat lpt_attach (UNIT *uptr, char *cptr) { -cctptr = 0; /* clear cct ptr */ -lines = 0; /* no cc action */ +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 index 0c5bc222..0ca53190 100644 --- a/I1401/i1401_mt.c +++ b/I1401/i1401_mt.c @@ -1,6 +1,6 @@ /* i1401_mt.c: IBM 1401 magnetic tape simulator - Copyright (c) 1993-2004, Robert M. Supnik + Copyright (c) 1993-2005, 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"), @@ -19,47 +19,48 @@ 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 + 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 + 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 + 26-Aug-05 RMS Revised to use API for write lock check + 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 + 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. @@ -68,73 +69,77 @@ #include "i1401_defs.h" #include "sim_tape.h" -#define MT_NUMDR 7 /* #drives */ -#define MT_MAXFR (MAXMEMSIZE * 2) /* max transfer */ +#define MT_NUMDR 7 /* #drives */ +#define MT_MAXFR (MAXMEMSIZE * 2) /* max transfer */ -extern uint8 M[]; /* memory */ +extern uint8 M[]; /* memory */ extern int32 ind[64]; extern int32 BS, iochk; extern UNIT cpu_unit; -uint8 dbuf[MT_MAXFR]; /* tape buffer */ +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 + 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) } }; + { 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 } }; + { 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 } }; + { 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 }; - + "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 + unit = unit character + mod = modifier character Outputs: - status = status + status = status */ t_stat mt_func (int32 unit, int32 mod) @@ -144,49 +149,50 @@ 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 */ +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_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_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_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_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_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 */ + case BCD_U: /* unload */ + sim_tape_rewind (uptr); /* update position */ + return detach_unit (uptr); /* detach */ -default: - return STOP_INVM; } + 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 + unit = unit character + flag = normal, word mark, or binary mode + mod = modifier character Outputs: - status = status + 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 @@ -203,67 +209,81 @@ 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? */ +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; } + 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 (sim_tape_wrp (uptr)) 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) @@ -277,28 +297,38 @@ return mt_dev.units + unit; 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; } + + 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; } @@ -309,9 +339,10 @@ 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 */ +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; } @@ -321,9 +352,9 @@ 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 */ +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 index 88d2aed8..084b600c 100644 --- a/I1401/i1401_sys.c +++ b/I1401/i1401_sys.c @@ -19,28 +19,28 @@ 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 + 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-Jan-05 WVS Added address argument support - 14-Nov-04 WVS Added data printout support - 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 + 04-Jan-05 WVS Added address argument support + 14-Nov-04 WVS Added data printout support + 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 +#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; @@ -55,12 +55,12 @@ 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 + 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"; @@ -70,55 +70,53 @@ 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 }; + &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" - }; - + "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", + "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,... + (repeat count) column number,column number,column number,... The CCT entries are stored in cct[0:lnt-1], cctlnt contains the number of entries @@ -133,28 +131,32 @@ 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; } } +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] = { @@ -165,7 +167,8 @@ const char *opcode[64] = { 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 }; + "SBR", NULL, "ZA", "H", "CWM", NULL, NULL, NULL + }; /* Print an address from three characters */ @@ -181,90 +184,101 @@ else if (addr >= MAXMEMSIZE) fprintf (of, " %d*", addr & ADDRMASK); else fprintf (of, " %d", addr); return; } - + /* Print unknown opcode as data */ t_stat dcw (FILE *of, int32 op, t_value *val) { int32 i; -fprintf (of, "DCW @%c", bcd_to_ascii[op]); /* assume it's data */ +fprintf (of, "DCW @%c", bcd_to_ascii[op]); /* assume it's data */ for (i = 1; i < sim_emax; i++) { if (val[i] & WM) break; fprintf (of, "%c", bcd_to_ascii[val[i]]); - } + } fprintf (of, "@"); -return -(i - 1); /* return # chars */ +return -(i - 1); /* return # chars */ } /* Symbolic decode Inputs: - *of = output stream - addr = current address - *val = values to decode - *uptr = pointer to unit - sw = switches + *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 + 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) + 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 ('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)) /* CPU? */ + return SCPE_ARG; 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); } + 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 */ -if (opcode[op] == NULL) return dcw (of, op, val); /* invalid 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? */ +if ((val[0] & WM) == 0) return STOP_NOWM; /* WM under op? */ +op = val[0]& CHAR; /* isolate op */ +if (opcode[op] == NULL) return dcw (of, op, val); /* invalid op */ +flags = op_table[op]; /* get flags */ +for (ilnt = 1; ilnt < sim_emax; ilnt++) { /* find inst lnt */ + 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 (ilnt == 3) { /* lnt = 3? */ - fprintf (of, "DSA"); /* assume DSA */ - fprint_addr (of, val); /* print addr */ - return -(ilnt - 1); } -if ((((flags & len_table[ilnt]) == 0) && /* invalid lnt, */ - (op != OP_NOP)) || /* not nop? */ - (opcode[op] == NULL)) return dcw (of, op, val); /* or undef? */ -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 */ +else if ((ilnt > 8) && (op != OP_NOP)) ilnt = 8; /* cap length */ +if (ilnt == 3) { /* lnt = 3? */ + fprintf (of, "DSA"); /* assume DSA */ + fprint_addr (of, val); /* print addr */ + return -(ilnt - 1); + } +if ((((flags & len_table[ilnt]) == 0) && /* invalid lnt, */ + (op != OP_NOP)) || /* not nop? */ + (opcode[op] == NULL)) /* or undef? */ + return dcw (of, op, val); +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) @@ -273,13 +287,14 @@ int32 addr, index; t_stat r; char gbuf[CBUFSIZE]; -cptr = get_glyph (cptr, gbuf, ','); /* get address */ +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; } +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); @@ -293,24 +308,24 @@ return SCPE_OK; t_stat get_io (char *cptr, t_value *val) { if ((cptr[0] != '%') || (cptr[3] != 0) || !isalnum (cptr[1]) || - !isalnum (cptr[2])) return SCPE_ARG; + !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 + *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 + 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) @@ -320,43 +335,50 @@ extern int32 op_table[64], len_table[9]; char gbuf[CBUFSIZE]; cflag = (uptr == NULL) || (uptr == &cpu_unit); -while (isspace (*cptr)) cptr++; /* absorb spaces */ +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); } + 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 (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? */ + 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 index 1bd6116f..75bf72ea 100644 --- a/I1620/i1620_cd.c +++ b/I1620/i1620_cd.c @@ -1,6 +1,6 @@ /* i1620_cd.c: IBM 1622 card reader/punch - Copyright (c) 2002-2004, Robert M. Supnik + Copyright (c) 2002-2005, 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"), @@ -19,14 +19,14 @@ 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 + 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 + cdr 1622 card reader + cdp 1622 card punch - 25-Apr-03 RMS Revised for extended file support + 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. @@ -34,7 +34,7 @@ #include "i1620_defs.h" -#define CD_LEN 80 +#define CD_LEN 80 extern uint8 M[MAXMEMSIZE]; extern uint8 ind[NUM_IND]; @@ -51,48 +51,54 @@ 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 + 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) }; + 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 } }; + { 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 }; + "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 + 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) }; + UDATA (NULL, UNIT_SEQ+UNIT_ATTABLE, 0) + }; REG cdp_reg[] = { - { DRDATA (POS, cdp_unit.pos, T_ADDR_W), PV_LEFT }, - { NULL } }; + { 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 }; - + "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 ]). @@ -102,30 +108,32 @@ DEVICE cdp_dev = { /* Card reader (ASCII) to numeric (one digit) */ const char cdr_to_num[128] = { - 0x00, -1, -1, -1, -1, -1, -1, -1, /* 00 */ + 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, /* 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 */ + 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 */ + '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, '"' }; + ']', 'J', 'K', 'L', 'M', 'N', 'O', 'P', /* F + 0 */ + 'Q', 'R', '!', '$', -1, -1, -1, '"' + }; /* Card reader (ASCII) to alphameric (two digits) @@ -137,35 +145,36 @@ const char num_to_cdp[32] = { */ const char cdr_to_alp[128] = { - 0x00, -1, -1, -1, -1, -1, -1, -1, /* 00 */ + 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, /* 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 */ + 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 + 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 (_), @@ -173,39 +182,40 @@ const char cdr_to_alp[128] = { */ const char alp_to_cdp[256] = { - ' ', -1, '?', '.', ')', -1, -1, '"', /* 00 */ + ' ', -1, '?', '.', ')', -1, -1, '"', /* 00 */ -1, -1, '\'', -1, -1, -1, -1, '&', - '+', -1, '!', '$', '*', ']', -1, -1, /* 10 */ + '+', -1, '!', '$', '*', ']', -1, -1, /* 10 */ -1, -1, -1, -1, -1, -1, -1, -1, - '-', '/', '\'', ',', '(', -1, -1, -1, /* 20 */ + '-', '/', '\'', ',', '(', -1, -1, -1, /* 20 */ -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, '%', '=', '@', ':', ' ', -1, /* 30 */ + -1, -1, '%', '=', '@', ':', ' ', -1, /* 30 */ -1, -1, '\'', -1, -1, -1, -1, '&', - -1, 'A', 'B', 'C', 'D', 'E', 'F', 'G', /* 40 */ + -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 */ + '_', 'J', 'K', 'L', 'M', 'N', 'O', 'P', /* 50 */ 'Q', 'R', '?', '=', -1, -1, -1, '"', - -1, '/', 'S', 'T', 'U', 'V', 'W', 'X', /* 60 */ + -1, '/', 'S', 'T', 'U', 'V', 'W', 'X', /* 60 */ 'Y', 'Z', '\'', ',', -1, -1, -1, -1, - '0', '1', '2', '3', '4', '5', '6', '7', /* 70 */ + '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, /* 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, /* 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, /* 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, /* 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, /* 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, /* 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, /* 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 }; - + -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. @@ -219,34 +229,43 @@ 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; } +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); } @@ -256,23 +275,25 @@ 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; } +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" */ +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; } @@ -280,7 +301,7 @@ return SCPE_OK; t_stat cdr_attach (UNIT *uptr, char *cptr) { -ind[IN_LAST] = 0; /* clear last card */ +ind[IN_LAST] = 0; /* clear last card */ return attach_unit (uptr, cptr); } @@ -288,33 +309,34 @@ return attach_unit (uptr, cptr); t_stat cdr_reset (DEVICE *dptr) { -ind[IN_LAST] = 0; /* clear last card */ +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 */ + 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)) +#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 */ +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. @@ -328,25 +350,33 @@ 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; +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 */ + break; + } + +return STOP_INVFNC; } /* Punch card numeric */ @@ -358,21 +388,24 @@ 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? */ +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; } @@ -380,20 +413,22 @@ return SCPE_OK; t_stat cdp_write (uint32 len) { -if ((cdp_unit.flags & UNIT_ATT) == 0) { /* attached? */ - ind[IN_WRCHK] = 1; /* no, error */ - return SCPE_UNATT; } +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 */ +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 */ +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; } diff --git a/I1620/i1620_cpu.c b/I1620/i1620_cpu.c index e481f990..a3b5ac2a 100644 --- a/I1620/i1620_cpu.c +++ b/I1620/i1620_cpu.c @@ -1,6 +1,6 @@ /* i1620_cpu.c: IBM 1620 CPU simulator - Copyright (c) 2002-2004, Robert M. Supnik + Copyright (c) 2002-2005, 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"), @@ -19,30 +19,31 @@ 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 + 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. - 07-Nov-04 RMS Added instruction history - 26-Mar-04 RMS Fixed warnings with -std=c99 - 02-Nov-03 RMS Fixed bug in branch digit (found by Dave Babcock) - 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) + 16-Aug-05 RMS Fixed C++ declaration and cast problems + 07-Nov-04 RMS Added instruction history + 26-Mar-04 RMS Fixed warnings with -std=c99 + 02-Nov-03 RMS Fixed bug in branch digit (found by Dave Babcock) + 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 + 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 + 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. @@ -53,22 +54,21 @@ The 1620 uses a fixed, 12 digit instruction format: - oo ppppp qqqqq + oo ppppp qqqqq where - oo = opcode - ppppp = P (usually destination) address - qqqqq = Q (usually source) address + 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. + + 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. @@ -77,10 +77,10 @@ 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 + HALT instruction + breakpoint encountered + illegal addresses or instruction formats + I/O error in I/O simulator 2. Interrupts. The 1620 has no interrupt structure. @@ -89,47 +89,49 @@ 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 + 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 +#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 -#define HIST_PC 0x40000000 -#define HIST_MIN 64 -#define HIST_MAX 65536 -struct InstHistory { - uint16 vld; - uint16 pc; - uint8 inst[INST_LEN]; }; +#define HIST_PC 0x40000000 +#define HIST_MIN 64 +#define HIST_MAX 65536 -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 */ -int32 hst_p = 0; /* history pointer */ -int32 hst_lnt = 0; /* history length */ -struct InstHistory *hst = NULL; /* instruction history */ -uint8 ind[NUM_IND] = { 0 }; /* indicators */ +typedef struct { + uint16 vld; + uint16 pc; + uint8 inst[INST_LEN]; + } InstHistory; + +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 */ +int32 hst_p = 0; /* history pointer */ +int32 hst_lnt = 0; /* history length */ +InstHistory *hst = NULL; /* instruction history */ +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 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); @@ -183,265 +185,272 @@ 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 + 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 } }; + { 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 }, - { MTAB_XTD|MTAB_VDV|MTAB_NMO|MTAB_SHP, 0, "HISTORY", "HISTORY", - &cpu_set_hist, &cpu_show_hist }, - { 0 } }; + { 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 }, + { MTAB_XTD|MTAB_VDV|MTAB_NMO|MTAB_SHP, 0, "HISTORY", "HISTORY", + &cpu_set_hist, &cpu_show_hist }, + { 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 }; - + "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 - }; - + 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 }; + 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 */ + -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 }; - + 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 }; + 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)) + 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) { @@ -454,536 +463,569 @@ t_stat reason; 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 */ +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; } +while (reason == 0) { /* loop until halted */ -if (sim_brk_summ && sim_brk_test (PC, SWMASK ('E'))) { /* breakpoint? */ - reason = STOP_IBKPT; /* stop simulation */ - break; } + saved_PC = PC; /* commit prev instr */ + if (sim_interval <= 0) { /* check clock queue */ + if (reason = sim_process_event ()) break; + } -sim_interval = sim_interval - 1; + 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; } + 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; } + 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? */ + 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? */ -if (hst_lnt) { /* history enabled? */ - hst_p = (hst_p + 1); /* next entry */ - if (hst_p >= hst_lnt) hst_p = 0; - hst[hst_p].vld = 1; - hst[hst_p].pc = PC; - for (i = 0; i < INST_LEN; i++) - hst[hst_p].inst[i] = M[(PC + i) % MEMSIZE]; - } + if (hst_lnt) { /* history enabled? */ + hst_p = (hst_p + 1); /* next entry */ + if (hst_p >= hst_lnt) hst_p = 0; + hst[hst_p].vld = 1; + hst[hst_p].pc = PC; + for (i = 0; i < INST_LEN; i++) + hst[hst_p].inst[i] = M[(PC + i) % MEMSIZE]; + } + + PC = PC + INST_LEN; /* advance PC */ + switch (op) { /* case on op */ -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; + 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; + 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; + 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 */ + 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; + 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; - + 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; + 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; + 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; + 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; + 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; + 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 (not zero) - P,Q are valid */ -case OP_BD: - if ((M[QAR] & DIGIT) != 0) { /* digit != 0? */ - BRANCH (PAR); } /* branch */ - break; + 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; + 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; + 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; + 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; - + 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_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_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; + 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; + 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; - + 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; + 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; + 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; + 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; + 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; - + 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; + 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; + 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; + 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_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; + 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_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; + 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; - + 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; + 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; + 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; + 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; + 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; + 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; + 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; + 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; - + 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_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_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_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_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_FSL: + reason = fp_fsl (PAR, QAR); /* shift left */ + break; -case OP_FSR: - reason = fp_fsr (PAR, QAR); /* shift right */ - 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; + case OP_H: + saved_PC = PC; /* commit inst */ + reason = STOP_HALT; /* stop */ + break; /* NOP */ -case OP_NOP: - break; + case OP_NOP: + break; /* Invalid instruction code */ -default: - reason = STOP_INVINS; /* stop */ - break; } /* end switch */ - } /* end while */ + default: + reason = STOP_INVINS; /* stop */ + break; + } /* end switch */ + } /* end while */ /* Simulation halted */ -pcq_r->qptr = pcq_p; /* update pc q ptr */ +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 + ad = address of high digit Outputs: - val = field converted to binary - -1 if bad digit + 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 */ +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 + 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 + return = error status (in terms of P address) + addr = address converted to binary Notes: - If indexing produces a negative result, the effective address is @@ -996,52 +1038,55 @@ 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 */ +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 */ +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 + alast = address of low digit + lnt = length + signok = TRUE if signed + val = address of output Outputs: - status = 0 if ok, != 0 if error + 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? */ +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; } @@ -1049,21 +1094,22 @@ return SCPE_OK; /* Get index register number Inputs: - aidx = address of low digit + aidx = address of low digit Outputs: - index = >0 if indexed - =0 if not indexed - <0 if indexing disabled + 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 */ +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; } @@ -1071,18 +1117,18 @@ return idx; void upd_ind (void) { -ind[IN_HPEZ] = ind[IN_HP] | ind[IN_EZ]; /* HPEZ = HP | EZ */ +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 */ +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 */ @@ -1092,10 +1138,11 @@ 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 */ +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; } @@ -1105,11 +1152,12 @@ 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 */ +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; } @@ -1119,12 +1167,13 @@ 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 */ +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; } @@ -1134,11 +1183,12 @@ 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 */ +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; } @@ -1149,19 +1199,20 @@ 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 */ +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; } @@ -1172,33 +1223,34 @@ 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 */ +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 + 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 + 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." @@ -1209,50 +1261,55 @@ t_stat add_field (uint32 d, uint32 s, t_bool sub, t_bool sto, uint32 skp, int32 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 */ +*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 */ +dst = M[d] & DIGIT; /* 1st digits */ src = M[s] & DIGIT; -if (BAD_DIGIT (dst) || BAD_DIGIT (src)) /* bad 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 */ +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; } @@ -1262,26 +1319,27 @@ 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 */ +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 + mpc = multiplicand address + mpy = multiplier address Outputs: - return = status + 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." @@ -1290,46 +1348,47 @@ return res & DIGIT; 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 */ +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 */ +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 */ +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 */ +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 */ +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) + 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 + prod += multiplicand * multiplier_digit + return = status The multiply table address is constructed as follows: - double the multiplier digit @@ -1343,61 +1402,62 @@ return SCPE_OK; 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 */ +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 */ +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 */ +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> + 100 - <# digits in quotient> Which is more easily calculated as: - 100 - <# digits in divisor> - <# digits in dividend> + 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) @@ -1421,99 +1481,99 @@ return SCPE_OK; The dividend is the field at 99: - 90 = _1234567890 + 90 = _1234567890 The divisor is somewhere else in memory: - _03 + _03 The divide operation specifies the left-most digit of the dividend as the place to begin trial subtractions: - DM 90,3 + 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. + 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 = _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 = _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 + 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 = _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: + 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 + 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. + 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 + 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. @@ -1525,54 +1585,57 @@ return SCPE_OK; 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 */ +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 */ +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? */ +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 */ + 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 */ +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) + 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 + return = status Divide step calculates a quotient digit by repeatedly subtracting the divisor from the current dividend. The divisor's length controls the @@ -1580,61 +1643,65 @@ return SCPE_OK; */ t_stat div_one_digit (uint32 dvd, uint32 dvr, uint32 max, - uint32 *quod, uint32 *quop) + 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 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 */ +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 */ +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 */ +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 + d = destination address + s = source address Output: - return = status + return = status Destination flags are preserved; EZ reflects the result. COM does not obey normal field length restrictions. @@ -1645,13 +1712,14 @@ 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 */ +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; } @@ -1660,13 +1728,14 @@ 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 */ +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; } @@ -1675,13 +1744,14 @@ 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 */ +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; } @@ -1690,24 +1760,25 @@ 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 */ +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 + tbl = conversion table address (low digit) + s = source address Outputs: - product area = converted source - result = status + 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 @@ -1721,39 +1792,40 @@ 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 */ +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 */ +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 + 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 + 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 @@ -1768,36 +1840,40 @@ 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 */ +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 */ + 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 { /* look for F, rec mk */ + PP (tbl); + 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) @@ -1805,18 +1881,18 @@ t_stat cpu_reset (DEVICE *dptr) int32 i; static t_bool one_time = TRUE; -PR1 = IR2 = 1; /* invalidate PR1,IR2 */ +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? */ +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 */ +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 */ +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; } @@ -1847,10 +1923,10 @@ int32 mc = 0; uint32 i; if ((val <= 0) || (val > MAXMEMSIZE) || ((val % 1000) != 0)) - return SCPE_ARG; + 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; + return SCPE_OK; MEMSIZE = val; for (i = MEMSIZE; i < MAXMEMSIZE; i++) M[i] = 0; return SCPE_OK; @@ -1861,7 +1937,7 @@ return SCPE_OK; 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; + IF_DIV | IF_IA | IF_EDT; else cpu_unit.flags = cpu_unit.flags & (UNIT_SCP | UNIT_BCD | MI_OPT); return SCPE_OK; } @@ -1871,9 +1947,10 @@ return SCPE_OK; 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; } + 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; } @@ -1882,9 +1959,10 @@ return SCPE_OK; 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; } + 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; } @@ -1903,11 +1981,12 @@ 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]; } +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; } @@ -1919,20 +1998,23 @@ int32 i, lnt; t_stat r; if (cptr == NULL) { - for (i = 0; i < hst_lnt; i++) hst[i].vld = 0; - hst_p = 0; - return SCPE_OK; } + for (i = 0; i < hst_lnt; i++) hst[i].vld = 0; + hst_p = 0; + return SCPE_OK; + } lnt = (int32) get_uint (cptr, 10, HIST_MAX, &r); if ((r != SCPE_OK) || (lnt && (lnt < HIST_MIN))) return SCPE_ARG; hst_p = 0; if (hst_lnt) { - free (hst); - hst_lnt = 0; - hst = NULL; } + free (hst); + hst_lnt = 0; + hst = NULL; + } if (lnt) { - hst = calloc (sizeof (struct InstHistory), lnt); - if (hst == NULL) return SCPE_MEM; - hst_lnt = lnt; } + hst = (InstHistory *) calloc (lnt, sizeof (InstHistory)); + if (hst == NULL) return SCPE_MEM; + hst_lnt = lnt; + } return SCPE_OK; } @@ -1944,31 +2026,32 @@ int32 i, k, di, lnt; char *cptr = (char *) desc; t_value sim_eval[INST_LEN]; t_stat r; -struct InstHistory *h; +InstHistory *h; extern t_stat fprint_sym (FILE *ofile, t_addr addr, t_value *val, - UNIT *uptr, int32 sw); + UNIT *uptr, int32 sw); -if (hst_lnt == 0) return SCPE_NOFNC; /* enabled? */ +if (hst_lnt == 0) return SCPE_NOFNC; /* enabled? */ if (cptr) { - lnt = (int32) get_uint (cptr, 10, hst_lnt, &r); - if ((r != SCPE_OK) || (lnt == 0)) return SCPE_ARG; } + lnt = (int32) get_uint (cptr, 10, hst_lnt, &r); + if ((r != SCPE_OK) || (lnt == 0)) return SCPE_ARG; + } else lnt = hst_lnt; -di = hst_p - lnt; /* work forward */ +di = hst_p - lnt; /* work forward */ if (di < 0) di = di + hst_lnt; fprintf (st, "PC IR\n\n"); -for (k = 0; k < lnt; k++) { /* print specified */ - h = &hst[(++di) % hst_lnt]; /* entry pointer */ - if (h->vld) { /* instruction? */ - fprintf (st, "%05d ", h->pc); - for (i = 0; i < INST_LEN; i++) - sim_eval[i] = h->inst[i]; - if ((fprint_sym (st, h->pc, sim_eval, &cpu_unit, SWMASK ('M'))) > 0) { - fprintf (st, "(undefined)"); - for (i = 0; i < INST_LEN; i++) - fprintf (st, "% 02X", h->inst[i]); - } - fputc ('\n', st); /* end line */ - } /* end else instruction */ - } /* end for */ +for (k = 0; k < lnt; k++) { /* print specified */ + h = &hst[(++di) % hst_lnt]; /* entry pointer */ + if (h->vld) { /* instruction? */ + fprintf (st, "%05d ", h->pc); + for (i = 0; i < INST_LEN; i++) + sim_eval[i] = h->inst[i]; + if ((fprint_sym (st, h->pc, sim_eval, &cpu_unit, SWMASK ('M'))) > 0) { + fprintf (st, "(undefined)"); + for (i = 0; i < INST_LEN; i++) + fprintf (st, "% 02X", h->inst[i]); + } + fputc ('\n', st); /* end line */ + } /* end else instruction */ + } /* end for */ return SCPE_OK; } diff --git a/I1620/i1620_defs.h b/I1620/i1620_defs.h index 0c817e44..6f32af3a 100644 --- a/I1620/i1620_defs.h +++ b/I1620/i1620_defs.h @@ -1,6 +1,6 @@ /* i1620_defs.h: IBM 1620 simulator definitions - Copyright (c) 2002-2004, Robert M. Supnik + Copyright (c) 2002-2005, 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"), @@ -19,203 +19,208 @@ 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 + 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) + 18-Oct-02 RMS Fixed bug in ADDR_S macro (found by Hans Pufal) */ -#include "sim_defs.h" /* simulator defns */ +#ifndef _I1620_DEFS_H_ +#define _I1620_DEFS_H_ 0 + +#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 */ +#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 */ +#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) +#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 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 */ +#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 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 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 LPT_WIDTH 120 /* line print width */ +#define CCT_LNT 132 /* car ctrl length */ -#define CRETIOE(f,c) return ((f)? (c): SCPE_OK) +#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) +#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 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) +#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) +#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 */ +#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 }; + 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 }; + +#endif diff --git a/I1620/i1620_doc.txt b/I1620/i1620_doc.txt index 78670b72..ae0b1609 100644 --- a/I1620/i1620_doc.txt +++ b/I1620/i1620_doc.txt @@ -7,8 +7,8 @@ Date: 15-Nov-2004 The following copyright notice applies to both the SIMH source and binary: - Original code published in 1993-2004, written by Robert M Supnik - Copyright (c) 1993-2004, Robert M Supnik + Original code published in 1993-2005, written by Robert M Supnik + Copyright (c) 1993-2005, 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"), @@ -27,8 +27,8 @@ The following copyright notice applies to both the SIMH source and binary: 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 + 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 diff --git a/I1620/i1620_dp.c b/I1620/i1620_dp.c index 6a2da846..a99e90bb 100644 --- a/I1620/i1620_dp.c +++ b/I1620/i1620_dp.c @@ -1,6 +1,6 @@ /* i1620_dp.c: IBM 1311 disk simulator - Copyright (c) 2002-2004, Robert M. Supnik + Copyright (c) 2002-2005, 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"), @@ -19,71 +19,71 @@ 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 + 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 + 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 + 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) + 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) +#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_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) +#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) +#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 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 */ +#define CYL u3 /* current cylinder */ -extern uint8 M[MAXMEMSIZE]; /* memory */ +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 */ +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); @@ -98,46 +98,50 @@ 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 + 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) } }; + { 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 } }; + { 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 } }; + { 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 }; - + "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) @@ -146,127 +150,141 @@ 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 */ +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? */ +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); } + (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! */ +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 */ +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 */ +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? */ -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 */ +switch (f1 & ~(FNC_WCH | FNC_NRL)) { /* case on function */ -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_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 + 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 */ + 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 */ -default: /* unknown */ - return STOP_INVFNC; } + 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 */ -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 */ + 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} ; +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 */ +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; } @@ -275,19 +293,22 @@ return SCPE_OK; 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 */ +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 */ +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; } @@ -296,17 +317,18 @@ return SCPE_OK; 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 */ +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 */ - } +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; } @@ -315,47 +337,51 @@ return SCPE_OK; 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 */ +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 */ - } +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 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 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 */ +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; } @@ -363,19 +389,20 @@ return -1; 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 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 */ +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; } @@ -385,18 +412,20 @@ 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 */ +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; } +if (!qnr && ((c & DIGIT) == GRP_MARK)) { /* premature GM? */ + ind[IN_DWLR] = ind[IN_DERR] = 1; /* error */ + return STOP_WRLERR; + } return SCPE_OK; } @@ -407,10 +436,11 @@ 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 */ +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; } @@ -421,7 +451,7 @@ 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)); + (ctrk * DP_NUMSC)); } /* Convert DCF BCD field to binary */ @@ -431,11 +461,12 @@ 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 */ +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; } @@ -443,10 +474,11 @@ return r; 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++; } +while (cnt-- > 0) { /* fill with zeroes*/ + *(((uint8 *) uptr->filebuf) + da) = 0; + if (da >= uptr->hwmark) uptr->hwmark = da + 1; + da++; + } return; } @@ -456,8 +488,8 @@ 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 */ +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 index f1035749..7b600265 100644 --- a/I1620/i1620_fp.c +++ b/I1620/i1620_fp.c @@ -1,6 +1,6 @@ /* i1620_fp.c: IBM 1620 floating point simulator - Copyright (c) 2002-2004, Robert M. Supnik + Copyright (c) 2002-2005, 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"), @@ -19,38 +19,36 @@ 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 + 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 + _ 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 */ +#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 { + int32 sign; /* 0 => +, 1 => - */ + int32 exp; /* binary exponent */ + uint32 lnt; /* mantissa length */ + uint32 addr; /* mantissa addr */ + uint32 zero; /* 0 => nz, 1 => zero */ + } FPA; -typedef struct fp_opnd FPA; - -extern uint8 M[MAXMEMSIZE]; /* main memory */ -extern uint8 ind[NUM_IND]; /* indicators */ +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); @@ -61,23 +59,23 @@ 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 */ +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 */ +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 */ +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)); } @@ -87,9 +85,9 @@ 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 */ +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; } @@ -100,18 +98,20 @@ 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); +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; } @@ -121,14 +121,15 @@ 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); } +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; } @@ -138,12 +139,13 @@ 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 */ +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; } @@ -153,12 +155,13 @@ 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 */ +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; } @@ -169,16 +172,18 @@ 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 */ +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 */ @@ -187,12 +192,13 @@ void fp_copy_mant (uint32 d, uint32 s, uint32 l) { uint32 i; -if (ind[IN_HP]) M[d] = M[d] & ~FLAG; /* clr/set sign */ +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); } +for (i = 0; i < l; i++) { /* copy src */ + M[d] = (M[d] & FLAG) | (M[s] & DIGIT); /* preserve flags */ + MM (d); + MM (s); + } return; } @@ -202,18 +208,19 @@ int32 fp_comp_mant (uint32 d, uint32 s, uint32 l) { uint8 i, dd, sd; -d = ADDR_S (d, l - 1); /* start of mantissa */ +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; /* 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 (sfp.zero || (dif >= ((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? */ +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 */ +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 */ +return fp_pack (&dfp); /* pack and exit */ } /* Floating point multiply */ @@ -280,20 +298,23 @@ 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 = 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 */ +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 */ +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 */ +return fp_pack (&dfp); /* pack and exit */ } /* Floating point divide */ @@ -305,31 +326,35 @@ 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? */ +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? */ +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 */ +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); } @@ -341,22 +366,24 @@ t_stat fp_fsr (uint32 d, uint32 s) uint32 cnt; uint8 t; -if (d == s) return SCPE_OK; /* no move? */ +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 */ +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 */ +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; } @@ -369,20 +396,22 @@ 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 */ +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 index 908f20fc..d8bf3d2c 100644 --- a/I1620/i1620_lp.c +++ b/I1620/i1620_lp.c @@ -1,6 +1,6 @@ /* i1620_lp.c: IBM 1443 line printer simulator - Copyright (c) 2002-2004, Robert M. Supnik + Copyright (c) 2002-2005, 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"), @@ -19,36 +19,36 @@ 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 + 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 + lpt 1443 line printer - 29-Dec-03 RMS Fixed bug in scheduling - 25-Apr-03 RMS Revised for extended file support + 29-Dec-03 RMS Fixed bug in scheduling + 25-Apr-03 RMS Revised for extended file support */ #include "i1620_defs.h" -#define LPT_BSIZE 197 /* buffer size */ +#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 */ +#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 */ +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); @@ -58,38 +58,41 @@ 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))) - +#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 + 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) }; + 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 } }; + { 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 }; - + "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) */ @@ -98,44 +101,46 @@ 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' }; + '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, /* 00 */ -1, -1, -1, -1, -1, -1, -1, -1, - '+', -1, '!', '$', '*', ' ', -1, -1, /* 10 */ + '+', -1, '!', '$', '*', ' ', -1, -1, /* 10 */ -1, -1, -1, -1, -1, -1, -1, -1, - '-', '/', '\'', ',', '(', -1, -1, -1, /* 20 */ + '-', '/', '\'', ',', '(', -1, -1, -1, /* 20 */ -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, '0', '=', '@', ':', -1, -1, /* 30 */ + -1, -1, '0', '=', '@', ':', -1, -1, /* 30 */ -1, -1, -1, -1, -1, -1, -1, -1, - -1, 'A', 'B', 'C', 'D', 'E', 'F', 'G', /* 40 */ + -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 */ + '-', 'J', 'K', 'L', 'M', 'N', 'O', 'P', /* 50 */ 'Q', 'R', -1, -1, -1, -1, -1, -1, - -1, '/', 'S', 'T', 'U', 'V', 'W', 'X', /* 60 */ + -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 */ + '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, /* 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, /* 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, /* 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, /* 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, /* 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, /* 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, /* 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 }; - + -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. @@ -149,38 +154,48 @@ int8 lpc; uint8 z, d; t_stat r, inv = SCPE_OK; -sim_cancel (&lpt_unit); /* "stall" until */ -ind[IN_PRBSY] = 0; /* printer free */ +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; + } -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) @@ -191,19 +206,22 @@ 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; } +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); } @@ -213,67 +231,75 @@ 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; } +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.wait); /* start timer */ +ind[IN_PRBSY] = 1; /* print busy */ +sim_activate (&lpt_unit, lpt_unit.wait); /* start timer */ -for (i = LPT_WIDTH; i <= LPT_BSIZE; i++) /* clear unprintable */ - lpt_buf[i] = ' '; +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_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; } +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 */ +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) + 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 */ +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; } +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; } @@ -300,10 +326,10 @@ return; 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 */ +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; } diff --git a/I1620/i1620_pt.c b/I1620/i1620_pt.c index 9617c173..1ff268b1 100644 --- a/I1620/i1620_pt.c +++ b/I1620/i1620_pt.c @@ -1,6 +1,6 @@ /* i1620_pt.c: IBM 1621/1624 paper tape reader/punch simulator - Copyright (c) 2002-2004, Robert M Supnik + Copyright (c) 2002-2005, 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"), @@ -19,23 +19,23 @@ 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 + 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 + ptr 1621 paper tape reader + ptp 1624 paper tape punch - 25-Apr-03 RMS Revised for extended file support + 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 */ +#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]; @@ -48,147 +48,158 @@ 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 + 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) }; + UDATA (NULL, UNIT_SEQ+UNIT_ATTABLE+UNIT_ROABLE, 0) + }; REG ptr_reg[] = { - { DRDATA (POS, ptr_unit.pos, T_ADDR_W), PV_LEFT }, - { NULL } }; + { 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 }; + "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 + 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) }; + UDATA (NULL, UNIT_SEQ+UNIT_ATTABLE, 0) + }; REG ptp_reg[] = { - { DRDATA (POS, ptp_unit.pos, T_ADDR_W), PV_LEFT }, - { NULL } }; + { 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 }; - + "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 */ + 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, /* - */ + 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 */ + 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 */ + 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 */ + 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 */ + 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 */ + 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 */ + 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 }; + 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, /* - */ + 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 */ + 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 */ + 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 */ + 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 */ + 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 */ + 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 */ + 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 }; + 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 */ + 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 }; + 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 */ + 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 */ + 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 */ + 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, 0x1A, 0x0B, 0x1C, 0x0D, 0x0E, -1, /* 30 */ -1, -1, -1, -1, -1, -1, -1, -1, - -1, 0x61, 0x62, 0x73, 0x64, 0x75, 0x76, 0x67, /* 40 */ + -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 */ + 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 */ + -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 */ + 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, /* 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, /* 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, /* 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, /* 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, /* 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, /* 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, /* 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 }; - + -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. @@ -204,40 +215,51 @@ 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; } +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; } @@ -250,25 +272,33 @@ 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; } + +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; } @@ -278,20 +308,23 @@ 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; } +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 */ +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; } @@ -305,16 +338,17 @@ 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 */ + 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)) +#define BOOT_START 0 +#define BOOT_LEN (sizeof (boot_rom) / sizeof (uint8)) t_stat ptr_boot (int32 unitno, DEVICE *dptr) { @@ -325,7 +359,7 @@ 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. @@ -340,27 +374,35 @@ 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; } +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; } @@ -373,21 +415,27 @@ 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; } + +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; } @@ -400,14 +448,15 @@ 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 */ +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; } @@ -415,16 +464,17 @@ return STOP_RWRAP; 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 */ +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; } diff --git a/I1620/i1620_sys.c b/I1620/i1620_sys.c index 09b95a63..20a5d56b 100644 --- a/I1620/i1620_sys.c +++ b/I1620/i1620_sys.c @@ -1,6 +1,6 @@ /* i1620_sys.c: IBM 1620 simulator interface - Copyright (c) 2002-2004, Robert M. Supnik + Copyright (c) 2002-2005, 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"), @@ -19,15 +19,15 @@ 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 + 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 +#define LINE_LNT 50 extern DEVICE cpu_dev, tty_dev; extern DEVICE ptr_dev, ptp_dev; @@ -41,12 +41,12 @@ 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 + 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"; @@ -56,63 +56,65 @@ 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 }; + &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" }; - + "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,... + (repeat count) column number,column number,column number,... The CCT entries are stored in cct[0:lnt-1], cctlnt contains the number of entries @@ -127,248 +129,268 @@ 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; } } +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 */ -}; + 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_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) +#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 }, + { "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 } + }; - { "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 */ +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 + *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 + 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) + 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 ('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); } + 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 (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? */ +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); } } +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) @@ -377,42 +399,45 @@ 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 */ +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; } +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 */ +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 + *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 + 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) @@ -420,71 +445,82 @@ 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 */ +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 ((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 ((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; /* 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 */ +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; } +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; } +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; } +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 */ +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 index 3f407051..1ba89410 100644 --- a/I1620/i1620_tty.c +++ b/I1620/i1620_tty.c @@ -1,6 +1,6 @@ /* i1620_tty.c: IBM 1620 typewriter - Copyright (c) 2002-2004, Robert M. Supnik + Copyright (c) 2002-2005, 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"), @@ -19,18 +19,18 @@ 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 + 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 + tty console typewriter - 22-Dec-02 RMS Added break test + 22-Dec-02 RMS Added break test */ #include "i1620_defs.h" -#define TTO_COLMAX 80 +#define TTO_COLMAX 80 int32 tto_col = 0; @@ -50,24 +50,26 @@ t_stat tty_reset (DEVICE *dptr); /* TTY data structures - tty_dev TTY device descriptor - tty_unit TTY unit descriptor - tty_reg TTY register list + 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 } }; + { 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 }; - + "TTY", &tty_unit, tty_reg, NULL, + 1, 10, 31, 1, 8, 7, + NULL, NULL, &tty_reset, + NULL, NULL, NULL + }; + /* Data tables */ /* Keyboard to numeric */ @@ -77,65 +79,68 @@ 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, /* 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, /* 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 */ + 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', '\'', '=', '@', ':', ';', '"' }; + '8', '9', '\'', '=', '@', ':', ';', '"' + }; /* Alphameric (digit pair) to typewriter */ const char alp_to_tto[256] = { - ' ', -1, '?', '.', ')', -1, -1, -1, /* 00 */ + ' ', -1, '?', '.', ')', -1, -1, -1, /* 00 */ -1, -1, -1, -1, -1, -1, -1, -1, - '+', -1, '!', '$', '*', ' ', -1, -1, /* 10 */ + '+', -1, '!', '$', '*', ' ', -1, -1, /* 10 */ -1, -1, -1, -1, -1, -1, -1, -1, - '-', '/', '\'', ',', '(', -1, -1, -1, /* 20 */ + '-', '/', '\'', ',', '(', -1, -1, -1, /* 20 */ -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, '0', '=', '@', ':', -1, -1, /* 30 */ + -1, -1, '0', '=', '@', ':', -1, -1, /* 30 */ -1, -1, -1, -1, -1, -1, -1, -1, - -1, 'A', 'B', 'C', 'D', 'E', 'F', 'G', /* 40 */ + -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 */ + '-', 'J', 'K', 'L', 'M', 'N', 'O', 'P', /* 50 */ 'Q', 'R', -1, -1, -1, -1, -1, -1, - -1, '/', 'S', 'T', 'U', 'V', 'W', 'X', /* 60 */ + -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 */ + '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, /* 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, /* 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, /* 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, /* 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, /* 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, /* 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, /* 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 }; - + -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. @@ -151,70 +156,84 @@ 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; } +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) @@ -223,16 +242,17 @@ int8 raw, flg = 0; char *cp; 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); +*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; } @@ -243,15 +263,16 @@ t_stat tti_ralp (int8 *c) int8 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); +*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; } @@ -261,13 +282,14 @@ 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 */ +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) @@ -277,15 +299,16 @@ 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 */ +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; } @@ -295,25 +318,29 @@ 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; } +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; } @@ -324,8 +351,8 @@ 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? */ +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; } @@ -333,7 +360,7 @@ return SCPE_OK; t_stat tty_reset (DEVICE *dptr) { -sim_activate (&tty_unit, tty_unit.wait); /* activate poll */ +sim_activate (&tty_unit, tty_unit.wait); /* activate poll */ tto_col = 0; return SCPE_OK; } diff --git a/Ibm1130/readme1130.txt b/Ibm1130/readme1130.txt index e7a20831..d2b5da29 100644 --- a/Ibm1130/readme1130.txt +++ b/Ibm1130/readme1130.txt @@ -186,4 +186,4 @@ Subnote: DMS cannot be built with the 1130's native assembler. -------------------------------------------------------------------------- -check www.ibm1130.org for updates... \ No newline at end of file +check www.ibm1130.org for updates... diff --git a/Interdata/id16_cpu.c b/Interdata/id16_cpu.c index 9146f435..d8770344 100644 --- a/Interdata/id16_cpu.c +++ b/Interdata/id16_cpu.c @@ -19,29 +19,31 @@ 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 + 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 Interdata 16b CPU + cpu Interdata 16b CPU - 10-Mar-05 RMS Fixed bug in show history routine (from Mark Hittinger) - Revised examine/deposit to do words rather than bytes - 07-Nov-04 RMS Added instruction history - 22-Sep-03 RMS Added additional instruction decode types - 07-Feb-03 RMS Fixed bug in SETM, SETMR (found by Mark Pizzolato) + 25-Aug-05 RMS Fixed DH integer overflow cases + 16-Aug-05 RMS Fixed C++ declaration and cast problems + 10-Mar-05 RMS Fixed bug in show history routine (from Mark Hittinger) + Revised examine/deposit to do words rather than bytes + 07-Nov-04 RMS Added instruction history + 22-Sep-03 RMS Added additional instruction decode types + 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 + 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. @@ -49,24 +51,24 @@ 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - | op | R1 | R2 | register-register + | 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 + | 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 + | 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 + | op | R1 | RX | register-storage +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | address | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ @@ -74,20 +76,20 @@ For register-memory and register-storage instructions, an effective address is calculated as follows: - effective addr = address + RX (if RX > 0) + 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 + 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 @@ -100,9 +102,8 @@ 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. + + 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. @@ -111,11 +112,11 @@ 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 + 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, @@ -130,90 +131,92 @@ 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 + 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 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 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 HIST_MIN 64 -#define HIST_MAX 65536 -struct InstHistory { - uint16 vld; - uint16 pc; - uint16 ir1; - uint16 ir2; - uint16 r1; - uint16 ea; - uint16 opnd; }; +#define HIST_MIN 64 +#define HIST_MAX 65536 -#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 hst_p = 0; /* history pointer */ -uint32 hst_lnt = 0; /* history length */ -struct InstHistory *hst = NULL; /* instruction history */ -struct BlockIO blk_io; /* block I/O status */ +typedef struct { + uint16 vld; + uint16 pc; + uint16 ir1; + uint16 ir2; + uint16 r1; + uint16 ea; + uint16 opnd; + } InstHistory; + +#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 hst_p = 0; /* history pointer */ +uint32 hst_lnt = 0; /* history length */ +InstHistory *hst = NULL; /* instruction history */ +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 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); @@ -246,288 +249,295 @@ 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_NO | 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_RR, /* LDBR */ - OP_RR | 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_RXB, /* LDB */ - OP_RXB | 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 }; + 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_NO | 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_RR, /* LDBR */ + OP_RR | 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_RXB, /* LDB */ + OP_RXB | 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 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 + }; -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 + 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) }; +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 (BLKIOD, blk_io.dfl, 16), REG_HRO }, - { HRDATA (BLKIOC, blk_io.cur, 16), REG_HRO }, - { HRDATA (BLKIOE, blk_io.end, 16), REG_HRO }, - { NULL } }; + { 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 (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 }, - { MTAB_XTD|MTAB_VDV|MTAB_NMO|MTAB_SHP, 0, "HISTORY", "HISTORY", - &cpu_set_hist, &cpu_show_hist }, - { 0 } }; + { 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 }, + { MTAB_XTD|MTAB_VDV|MTAB_NMO|MTAB_SHP, 0, "HISTORY", "HISTORY", + &cpu_set_hist, &cpu_show_hist }, + { 0 } + }; DEVICE cpu_dev = { - "CPU", &cpu_unit, cpu_reg, cpu_mod, - 1, 16, 18, 2, 16, 16, - &cpu_ex, &cpu_dep, &cpu_reset, - NULL, NULL, NULL, - &cpu_dib, 0 }; - + "CPU", &cpu_unit, cpu_reg, cpu_mod, + 1, 16, 18, 2, 16, 16, + &cpu_ex, &cpu_dep, &cpu_reset, + NULL, NULL, NULL, + &cpu_dib, 0 + }; + t_stat sim_instr (void) { uint32 cc; @@ -535,776 +545,834 @@ 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 */ +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; -uint32 ir1, ir2, ityp; -int32 sr, st; +while (reason == 0) { /* loop until halted */ + uint32 dev, drom, inc, lim, opnd; + uint32 op, r1, r1p1, r2, ea, oPC; + uint32 rslt, t, map; + uint32 ir1, ir2, ityp; + int32 sr, st; -if (sim_interval <= 0) { /* check clock queue */ - if (reason = sim_process_event ()) break; - int_eval (); } + 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) { /* 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 ((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; } + 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 */ + } /* end if event */ - 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; } + if (sim_brk_summ && sim_brk_test (PC, SWMASK ('E'))) { /* breakpoint? */ + reason = STOP_IBKPT; /* stop simulation */ + break; + } -sim_interval = sim_interval - 1; + sim_interval = sim_interval - 1; -ir1 = ReadH (oPC = PC); /* fetch instr */ -op = (ir1 >> 8) & 0xFF; /* isolate op, R1, R2 */ -r1 = (ir1 >> 4) & 0xF; -r2 = ir1 & 0xF; -drom = decrom[op]; -ityp = drom & OP_MASK; + ir1 = ReadH (oPC = PC); /* fetch instr */ + op = (ir1 >> 8) & 0xFF; /* isolate op, R1, R2 */ + r1 = (ir1 >> 4) & 0xF; + r2 = ir1 & 0xF; + drom = decrom[op]; + ityp = drom & OP_MASK; -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; } + 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 (ityp) { /* decode instruction */ -case OP_NO: /* no operand */ - opnd = r2; /* assume short */ - break; + switch (ityp) { /* decode instruction */ -case OP_RR: /* reg-reg */ - opnd = R[r2]; /* operand is R2 */ - break; + case OP_NO: /* no operand */ + opnd = r2; /* assume short */ + break; -case OP_RS: /* reg-storage */ -case OP_RX: /* reg-mem */ - PC = (PC + 2) & VAMASK; /* increment PC */ - ir2 = ea = ReadH (PC); /* fetch address */ - if (r2) ea = (ir2 + R[r2]) & VAMASK; /* index calculation */ - opnd = ea; /* operand is ea */ - break; + case OP_RR: /* reg-reg */ + opnd = R[r2]; /* operand is R2 */ + break; -case OP_RXB: /* reg-mem byte */ - PC = (PC + 2) & VAMASK; /* increment PC */ - ir2 = ea = ReadH (PC); /* fetch address */ - if (r2) ea = (ea + R[r2]) & VAMASK; /* index calculation */ - opnd = ReadB (ea); /* fetch operand */ - break; + case OP_RS: /* reg-storage */ + case OP_RX: /* reg-mem */ + PC = (PC + 2) & VAMASK; /* increment PC */ + ir2 = ea = ReadH (PC); /* fetch address */ + if (r2) ea = (ir2 + R[r2]) & VAMASK; /* index calculation */ + opnd = ea; /* operand is ea */ + break; -case OP_RXH: /* reg-mem halfword */ - PC = (PC + 2) & VAMASK; /* increment PC */ - ir2 = ea = ReadH (PC); /* fetch address */ - if (r2) ea = (ea + R[r2]) & VAMASK; /* index calculation */ - opnd = ReadH (ea); /* fetch operand */ - break; - -default: - return SCPE_IERR; } + case OP_RXB: /* reg-mem byte */ + PC = (PC + 2) & VAMASK; /* increment PC */ + ir2 = ea = ReadH (PC); /* fetch address */ + if (r2) ea = (ea + R[r2]) & VAMASK; /* index calculation */ + opnd = ReadB (ea); /* fetch operand */ + break; -if (hst_lnt) { /* instruction history? */ - hst[hst_p].vld = 1; - hst[hst_p].pc = oPC; - hst[hst_p].ir1 = ir1; - hst[hst_p].ir2 = ir2; - hst[hst_p].r1 = R[r1]; - hst[hst_p].ea = ea; - hst[hst_p].opnd = opnd; - hst_p = hst_p + 1; - if (hst_p >= hst_lnt) hst_p = 0; } + case OP_RXH: /* reg-mem halfword */ + PC = (PC + 2) & VAMASK; /* increment PC */ + ir2 = ea = ReadH (PC); /* fetch address */ + if (r2) ea = (ea + R[r2]) & VAMASK; /* index calculation */ + opnd = ReadH (ea); /* fetch operand */ + break; + + default: + return SCPE_IERR; + } + + if (hst_lnt) { /* instruction history? */ + hst[hst_p].vld = 1; + hst[hst_p].pc = oPC; + hst[hst_p].ir1 = ir1; + hst[hst_p].ir2 = ir2; + hst[hst_p].r1 = R[r1]; + hst[hst_p].ea = ea; + hst[hst_p].opnd = opnd; + hst_p = hst_p + 1; + if (hst_p >= hst_lnt) hst_p = 0; + } + + PC = (PC + 2) & VAMASK; /* increment PC */ + switch (op) { /* case on opcode */ -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 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 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 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 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 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 - RR */ -case 0xD3: /* LDB - RXB */ - R[r1] = opnd & DMASK8; /* load byte */ - break; + case 0x93: /* LDBR - RR */ + case 0xD3: /* LDB - RXB */ + R[r1] = opnd & DMASK8; /* 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 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 - RR */ + R[r1] = (opnd >> 8) | ((opnd & DMASK8) << 8); + break; -case 0x94: /* EXBR - RR */ - R[r1] = (opnd >> 8) | ((opnd & 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 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 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 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 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 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 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 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 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; -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 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 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 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 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 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 - RXB */ + 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; -case 0xD4: /* CLB - RXB */ - 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 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 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 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 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 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 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 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 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 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; -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 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 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 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 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 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 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 0x0D: /* DHR - RR */ + case 0x4D: /* DH - RXH */ + r1p1 = (r1 + 1) & 0xF; /* R1 + 1 */ + if ((opnd == 0) || + ((R[r1] == 0x8000) && (R[r1p1] == 0) && (opnd = 0xFFFF))) { + if (PSW & PSW_AFI) /* div fault enabled? */ + cc = swap_psw (AFIPSW, cc); /* swap PSW */ + break; + } + sr = (R[r1] << 16) | R[r1p1]; /* signed 32b divd */ + st = sr / SEXT16 (opnd); /* signed quotient */ + sr = sr % SEXT16 (opnd); /* remainder */ + if ((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 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; -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 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 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 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 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 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 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 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 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 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 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 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 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; -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 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 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 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 - NO */ - 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 0x95: /* EPSR - NO */ + 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 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 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 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; -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 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 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 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 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 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; -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 @@ -1313,79 +1381,87 @@ case 0xDD: /* SS - RX */ 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 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 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 */ + 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 */ +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? */ +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 */ +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; } @@ -1393,51 +1469,54 @@ return PSW & CC_MASK; uint32 swap_psw (uint32 loc, uint32 cc) { -WriteH (loc, BUILD_PSW (cc)); /* write PSW, PC */ +WriteH (loc, BUILD_PSW (cc)); /* write PSW, PC */ WriteH (loc + 2, PC); -cc = newPSW (ReadH (loc + 4)); /* read PSW, 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 */ +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 */ +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); } +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 */ +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; } @@ -1446,30 +1525,33 @@ 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 */ +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 */ +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)) +#define CCW16_ERR(x) (((x)|CCW16_INIT|CCW16_NOP|CCW16_Q) & \ + ~(CCW16_CHN|CCW16_CON|CCW16_HI)) uint32 int_auto (uint32 dev, uint32 cc) { @@ -1478,86 +1560,97 @@ 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 */ + 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? */ + 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 */ +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) @@ -1565,44 +1658,52 @@ 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; } + + 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) + 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) @@ -1624,15 +1725,16 @@ uint32 ReadF (uint32 loc, uint32 rel) uint32 pa, pa1; uint32 loc1 = (loc + 2) & VAMASK; -loc = loc & VAMASK; /* FP doesn't mask */ +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]); + 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) @@ -1641,8 +1743,8 @@ 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))); + ((M[pa >> 1] & ~DMASK8) | val): + ((M[pa >> 1] & DMASK8) | (val << 8))); return; } @@ -1659,12 +1761,15 @@ void WriteF (uint32 loc, uint32 val, uint32 rel) uint32 pa, pa1; uint32 loc1 = (loc + 2) & VAMASK; -loc = loc & VAMASK; /* FP doesn't mask */ +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; } + 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; @@ -1679,8 +1784,8 @@ 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))); + ((M[loc >> 1] & ~DMASK8) | val): + ((M[loc >> 1] & DMASK8) | (val << 8))); return; } @@ -1694,20 +1799,20 @@ void IOWriteH (uint32 loc, uint32 val) M[loc >> 1] = val & DMASK16; return; } - + /* Reset routine */ t_stat cpu_reset (DEVICE *dptr) { -qevent = 0; /* no events */ -newPSW (0); /* PSW = 0 */ -DR = 0; /* clr display */ +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)); +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 = (uint16 *) calloc (MAXMEMSIZE16E >> 1, sizeof (uint16)); if (M == NULL) return SCPE_MEM; -pcq_r = find_reg ("PCQ", NULL, dptr); /* init PCQ */ +pcq_r = find_reg ("PCQ", NULL, dptr); /* init PCQ */ if (pcq_r) pcq_r->qptr = 0; else return SCPE_IERR; return SCPE_OK; @@ -1718,8 +1823,9 @@ return SCPE_OK; 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 > VAMASK) return SCPE_NXM; + addr = (addr + ((addr & VA_S1)? s1_rel: s0_rel)) & PAMASK16E; + } if (addr >= MEMSIZE) return SCPE_NXM; if (vptr != NULL) *vptr = IOReadH (addr); return SCPE_OK; @@ -1730,8 +1836,9 @@ return SCPE_OK; 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 > VAMASK) return SCPE_NXM; + addr = (addr + ((addr & VA_S1)? s1_rel: s0_rel)) & PAMASK16E; + } if (addr >= MEMSIZE) return SCPE_NXM; IOWriteH (addr, val); return SCPE_OK; @@ -1746,10 +1853,10 @@ uint32 i; if ((val <= 0) || ((val & 0xFFF) != 0) || (((uint32) val) > ((uptr->flags & UNIT_816E)? MAXMEMSIZE16E: MAXMEMSIZE16))) - return SCPE_ARG; + 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; + return SCPE_OK; MEMSIZE = val; for (i = MEMSIZE; i < MAXMEMSIZE16E; i = i + 2) M[i >> 1] = 0; return SCPE_OK; @@ -1762,9 +1869,10 @@ 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"); } + MEMSIZE = MAXMEMSIZE16; + for (i = MEMSIZE; i < MAXMEMSIZE16E; i = i + 2) M[i >> 1] = 0; + printf ("Reducing memory to 64KB\n"); + } return SCPE_OK; } @@ -1773,7 +1881,7 @@ return SCPE_OK; 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; + return SCPE_NOFNC; if (PSW & PSW_AIO) SET_INT (v_DS); return SCPE_OK; } @@ -1786,20 +1894,23 @@ uint32 i, lnt; t_stat r; if (cptr == NULL) { - for (i = 0; i < hst_lnt; i++) hst[i].vld = 0; - hst_p = 0; - return SCPE_OK; } + for (i = 0; i < hst_lnt; i++) hst[i].vld = 0; + hst_p = 0; + return SCPE_OK; + } lnt = (uint32) get_uint (cptr, 10, HIST_MAX, &r); if ((r != SCPE_OK) || (lnt && (lnt < HIST_MIN))) return SCPE_ARG; hst_p = 0; if (hst_lnt) { - free (hst); - hst_lnt = 0; - hst = NULL; } + free (hst); + hst_lnt = 0; + hst = NULL; + } if (lnt) { - hst = calloc (sizeof (struct InstHistory), lnt); - if (hst == NULL) return SCPE_MEM; - hst_lnt = lnt; } + hst = (InstHistory *) calloc (lnt, sizeof (InstHistory)); + if (hst == NULL) return SCPE_MEM; + hst_lnt = lnt; + } return SCPE_OK; } @@ -1811,31 +1922,32 @@ int32 op, k, di, lnt; char *cptr = (char *) desc; t_value sim_eval[2]; t_stat r; -struct InstHistory *h; +InstHistory *h; extern t_stat fprint_sym (FILE *ofile, t_addr addr, t_value *val, - UNIT *uptr, int32 sw); + UNIT *uptr, int32 sw); -if (hst_lnt == 0) return SCPE_NOFNC; /* enabled? */ +if (hst_lnt == 0) return SCPE_NOFNC; /* enabled? */ if (cptr) { - lnt = (int32) get_uint (cptr, 10, hst_lnt, &r); - if ((r != SCPE_OK) || (lnt == 0)) return SCPE_ARG; } + lnt = (int32) get_uint (cptr, 10, hst_lnt, &r); + if ((r != SCPE_OK) || (lnt == 0)) return SCPE_ARG; + } else lnt = hst_lnt; -di = hst_p - lnt; /* work forward */ +di = hst_p - lnt; /* work forward */ if (di < 0) di = di + hst_lnt; fprintf (st, "PC r1 opnd ea IR\n\n"); -for (k = 0; k < lnt; k++) { /* print specified */ - h = &hst[(di++) % hst_lnt]; /* entry pointer */ - if (h->vld) { /* instruction? */ - fprintf (st, "%04X %04X %04X ", h->pc, h->r1, h->opnd); - op = (h->ir1 >> 8) & 0xFF; - if (OP_TYPE (op) >= OP_RX) fprintf (st, "%04X ", h->ea); - else fprintf (st, " "); - sim_eval[0] = h->ir1; - sim_eval[1] = h->ir2; - if ((fprint_sym (st, h->pc, sim_eval, &cpu_unit, SWMASK ('M'))) > 0) - fprintf (st, "(undefined) %04X", h->ir1); - fputc ('\n', st); /* end line */ - } /* end if instruction */ - } /* end for */ +for (k = 0; k < lnt; k++) { /* print specified */ + h = &hst[(di++) % hst_lnt]; /* entry pointer */ + if (h->vld) { /* instruction? */ + fprintf (st, "%04X %04X %04X ", h->pc, h->r1, h->opnd); + op = (h->ir1 >> 8) & 0xFF; + if (OP_TYPE (op) >= OP_RX) fprintf (st, "%04X ", h->ea); + else fprintf (st, " "); + sim_eval[0] = h->ir1; + sim_eval[1] = h->ir2; + if ((fprint_sym (st, h->pc, sim_eval, &cpu_unit, SWMASK ('M'))) > 0) + fprintf (st, "(undefined) %04X", h->ir1); + fputc ('\n', st); /* end line */ + } /* end if instruction */ + } /* end for */ return SCPE_OK; } diff --git a/Interdata/id16_dboot.c b/Interdata/id16_dboot.c index ad6170f2..e2c25a95 100644 --- a/Interdata/id16_dboot.c +++ b/Interdata/id16_dboot.c @@ -1,6 +1,6 @@ /* id16_dboot.c: Interdata 16b simulator disk bootstrap - Copyright (c) 2000-2004, Robert M. Supnik + Copyright (c) 2000-2005, 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"), @@ -19,16 +19,16 @@ 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 + 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)) +#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 */ @@ -288,62 +288,64 @@ static uint8 dboot_rom[] = { 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) + 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; -}; + 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 } }; + { "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 */ +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 ((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 */ +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_DSKU, ctlno + ((u + 1) * off) + add); /* disk param */ IOWriteB (AL_DSKT, typ); IOWriteB (AL_DSKC, ctlno); IOWriteB (AL_SCH, sch_dev); diff --git a/Interdata/id16_sys.c b/Interdata/id16_sys.c index 1a4bf755..292c7ec6 100644 --- a/Interdata/id16_sys.c +++ b/Interdata/id16_sys.c @@ -1,6 +1,6 @@ /* id16_sys.c: Interdata 16b simulator interface - Copyright (c) 2000-2004, Robert M. Supnik + Copyright (c) 2000-2005, 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"), @@ -19,18 +19,18 @@ 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 + 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. - 26-Mar-04 RMS Fixed warning with -std=c99 - 27-Feb-03 RMS Added relative addressing support + 26-Mar-04 RMS Fixed warning with -std=c99 + 27-Feb-03 RMS Added relative addressing support */ #include "id_defs.h" #include -#define MSK_SBF 0x0100 +#define MSK_SBF 0x0100 extern DEVICE cpu_dev; extern DEVICE sch_dev; @@ -52,12 +52,12 @@ extern t_stat 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 + 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"; @@ -67,29 +67,31 @@ REG *sim_PC = &cpu_reg[0]; int32 sim_emax = 2; 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 }; + &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" }; + "Unknown error", + "Reserved instruction", + "HALT instruction", + "Breakpoint", + "Wait state", + "Runaway VFU" + }; /* Binary loader -- load carriage control tape Binary dump -- paper tape dump */ @@ -99,53 +101,56 @@ 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 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 */ +#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 }; + 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 }; + 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 }; + R_M, R_X, R_X + }; static const char *opcode[] = { "BER", "BNER","BZR", "BNZR", @@ -199,7 +204,8 @@ static const char *opcode[] = { "SVC", "SINT", "RRL", "RLL", "SRL", "SLL", "SRA", "SLA", -NULL }; +NULL +}; static const uint32 opc_val[] = { 0x0330+I_R, 0x0230+I_R, 0x0330+I_R, 0x0230+I_R, @@ -251,59 +257,65 @@ static const uint32 opc_val[] = { 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, + 0xEA00+I_RX, 0xEB00+I_RX, 0xEC00+I_RX, 0xED00+I_RX, 0xEE00+I_RX, 0xEF00+I_RX, -0xFFFF }; - +0xFFFF +}; + /* Symbolic decode Inputs: - *of = output stream - addr = current PC - *val = values to decode - *uptr = pointer to unit - sw = switches + *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 + 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) + UNIT *uptr, int32 sw) { int32 c1, c2, rdx; t_stat r; DEVICE *dptr; -if (uptr == NULL) uptr = &cpu_unit; /* anon = CPU */ -else if (uptr != &cpu_unit) return SCPE_ARG; /* CPU only */ -dptr = find_dev_from_unit (uptr); /* find dev */ +if (uptr == NULL) uptr = &cpu_unit; /* anon = CPU */ +else if (uptr != &cpu_unit) return SCPE_ARG; /* CPU only */ +dptr = find_dev_from_unit (uptr); /* find dev */ if (dptr == NULL) return SCPE_IERR; -if (sw & SWMASK ('D')) rdx = 10; /* get radix */ +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; -if (sw & SWMASK ('A')) { /* ASCII char? */ - c1 = (val[0] >> ((addr & 1)? 0: 8)) & 0x7F; /* get byte */ - fprintf (of, (c1 < 0x20)? "<%02X>": "%c", c1); - return 0; } -if (sw & SWMASK ('B')) { /* byte? */ - c1 = (val[0] >> ((addr & 1)? 0: 8)) & 0xFF; /* get byte */ - fprint_val (of, c1, rdx, 8, PV_RZRO); - return 0; } -if (sw & SWMASK ('C')) { /* string? */ - c1 = (val[0] >> 8) & 0x7F; - c2 = val[0] & 0x7F; - fprintf (of, (c1 < 0x20)? "<%02X>": "%c", c1); - fprintf (of, (c2 < 0x20)? "<%02X>": "%c", c2); - return -1; } -if (sw & SWMASK ('F')) { /* fullword? */ - fprint_val (of, (val[0] << 16) | val[1], rdx, 32, PV_RZRO); - return -3; } -if (sw & SWMASK ('M')) { /* inst format? */ - r = fprint_sym_m (of, addr, val); /* decode inst */ - if (r <= 0) return r; } +if (sw & SWMASK ('A')) { /* ASCII char? */ + c1 = (val[0] >> ((addr & 1)? 0: 8)) & 0x7F; /* get byte */ + fprintf (of, (c1 < 0x20)? "<%02X>": "%c", c1); + return 0; + } +if (sw & SWMASK ('B')) { /* byte? */ + c1 = (val[0] >> ((addr & 1)? 0: 8)) & 0xFF; /* get byte */ + fprint_val (of, c1, rdx, 8, PV_RZRO); + return 0; + } +if (sw & SWMASK ('C')) { /* string? */ + c1 = (val[0] >> 8) & 0x7F; + c2 = val[0] & 0x7F; + fprintf (of, (c1 < 0x20)? "<%02X>": "%c", c1); + fprintf (of, (c2 < 0x20)? "<%02X>": "%c", c2); + return -1; + } +if (sw & SWMASK ('F')) { /* fullword? */ + fprint_val (of, (val[0] << 16) | val[1], rdx, 32, PV_RZRO); + return -3; + } +if (sw & SWMASK ('M')) { /* inst format? */ + r = fprint_sym_m (of, addr, val); /* decode inst */ + if (r <= 0) return r; + } fprint_val (of, val[0], rdx, 16, PV_RZRO); return -1; @@ -312,12 +324,12 @@ return -1; /* Symbolic decode for -m Inputs: - of = output stream - addr = current PC - *val = values to decode + of = output stream + addr = current PC + *val = values to decode Outputs: - return = if >= 0, error code - if < 0, number of extra bytes retired + 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) @@ -325,73 +337,86 @@ t_stat fprint_sym_m (FILE *of, t_addr addr, t_value *val) uint32 i, j, inst, r1, r2, ea, vp; vp = 0; -inst = val[0]; /* first 16b */ -ea = val[1]; /* 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 */ - fprintf (of, "%-X", ((inst & MSK_SBF)? - (addr + r2 + r2): (addr - 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 */ +inst = val[0]; /* first 16b */ +ea = val[1]; /* 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 */ + fprintf (of, "%-X", ((inst & MSK_SBF)? + (addr + r2 + r2): (addr - 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 + *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 + 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 == '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; } + 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; @@ -403,33 +428,35 @@ return reg; /* Address Inputs: - *cptr = pointer to input string - **tptr = pointer to moved pointer - *ea = effective address - addr = base address + *cptr = pointer to input string + **tptr = pointer to moved pointer + *ea = effective address + addr = base address Outputs: - status = SCPE_OK if ok, else error code + status = SCPE_OK if ok, else error code */ t_stat get_addr (char *cptr, char **tptr, t_addr *ea, t_addr addr) { int32 sign = 1; -if (*cptr == '.') { /* relative? */ - cptr++; - *ea = addr; - if (*cptr == '+') cptr++; /* .+? */ - else if (*cptr == '-') { /* .-? */ - sign = -1; - cptr++; } - else return SCPE_OK; } +if (*cptr == '.') { /* relative? */ + cptr++; + *ea = addr; + if (*cptr == '+') cptr++; /* .+? */ + else if (*cptr == '-') { /* .-? */ + sign = -1; + cptr++; + } + else return SCPE_OK; + } else *ea = 0; errno = 0; *ea = *ea + (sign * ((int32) strtoul (cptr, tptr, 16))); if (errno || (cptr == *tptr)) return SCPE_ARG; return SCPE_OK; } - + /* Symbolic input */ t_stat parse_sym (char *cptr, t_addr addr, UNIT *uptr, t_value *val, int32 sw) @@ -438,40 +465,44 @@ int32 by, rdx, num; t_stat r; DEVICE *dptr; -if (uptr == NULL) uptr = &cpu_unit; /* anon = CPU */ -else if (uptr != &cpu_unit) return SCPE_ARG; /* CPU only */ -dptr = find_dev_from_unit (uptr); /* find dev */ +if (uptr == NULL) uptr = &cpu_unit; /* anon = CPU */ +else if (uptr != &cpu_unit) return SCPE_ARG; /* CPU only */ +dptr = find_dev_from_unit (uptr); /* find dev */ if (dptr == NULL) return SCPE_IERR; -if (sw & SWMASK ('D')) rdx = 10; /* get radix */ +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; if ((sw & SWMASK ('A')) || ((*cptr == '\'') && cptr++)) { /* ASCII char? */ - if (cptr[0] == 0) return SCPE_ARG; /* must have 1 char */ - if (addr & 1) val[0] = (val[0] & ~0xFF) | ((t_value) cptr[0]); - else val[0] = (val[0] & 0xFF) | (((t_value) cptr[0]) << 8); - return 0; } -if (sw & SWMASK ('B')) { /* byte? */ - by = get_uint (cptr, rdx, DMASK8, &r); /* get byte */ - if (r != SCPE_OK) return SCPE_ARG; - if (addr & 1) val[0] = (val[0] & ~0xFF) | by; - else val[0] = (val[0] & 0xFF) | (by << 8); - return 0; } + if (cptr[0] == 0) return SCPE_ARG; /* must have 1 char */ + if (addr & 1) val[0] = (val[0] & ~0xFF) | ((t_value) cptr[0]); + else val[0] = (val[0] & 0xFF) | (((t_value) cptr[0]) << 8); + return 0; + } +if (sw & SWMASK ('B')) { /* byte? */ + by = get_uint (cptr, rdx, DMASK8, &r); /* get byte */ + if (r != SCPE_OK) return SCPE_ARG; + if (addr & 1) val[0] = (val[0] & ~0xFF) | by; + else val[0] = (val[0] & 0xFF) | (by << 8); + return 0; + } if ((sw & SWMASK ('C')) || ((*cptr == '"') && cptr++)) { /* ASCII chars? */ - if (cptr[0] == 0) return SCPE_ARG; /* must have 1 char */ - val[0] = ((t_value) cptr[0] << 8) | (t_value) cptr[1]; - return -1; } + if (cptr[0] == 0) return SCPE_ARG; /* must have 1 char */ + val[0] = ((t_value) cptr[0] << 8) | (t_value) cptr[1]; + return -1; + } if (sw & SWMASK ('F')) { - num = (int32) get_uint (cptr, rdx, DMASK32, &r);/* get number */ - if (r != SCPE_OK) return r; - val[0] = (num >> 16) & DMASK16; - val[1] = num & DMASK16; - return -3; } + num = (int32) get_uint (cptr, rdx, DMASK32, &r); /* get number */ + if (r != SCPE_OK) return r; + val[0] = (num >> 16) & DMASK16; + val[1] = num & DMASK16; + return -3; + } -r = parse_sym_m (cptr, addr, val); /* try to parse inst */ +r = parse_sym_m (cptr, addr, val); /* try to parse inst */ if (r <= 0) return r; -val[0] = (int32) get_uint (cptr, rdx, DMASK16, &r); /* get number */ +val[0] = (int32) get_uint (cptr, rdx, DMASK16, &r); /* get number */ if (r != SCPE_OK) return r; return -1; } @@ -479,13 +510,13 @@ return -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 + *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 + status = > 0 error code + <= 0 -number of extra words */ t_stat parse_sym_m (char *cptr, t_addr addr, t_value *val) @@ -495,62 +526,64 @@ int32 st, r1, r2; t_stat r; char *tptr, gbuf[CBUFSIZE]; -cptr = get_glyph (cptr, gbuf, 0); /* get opcode */ +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 */ +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 */ +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_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, addr); /* get addr */ - if ((r != SCPE_OK) || (t > PAMASK16)) 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; - val[0] = inst; - val[1] = t; - return -3; + 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, addr); /* get addr */ + if ((r != SCPE_OK) || (t > PAMASK16)) 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; + val[0] = inst; + val[1] = t; + return -3; -case I_V_SB: case I_V_SX: /* short branches */ - r = get_addr (gbuf, &tptr, &t, addr); /* get addr */ - if ((r != SCPE_OK) || (t & 1) || *tptr) /* error if odd */ - return SCPE_ARG; - st = t; /* signed version */ - 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; - break; - } /* end case */ + case I_V_SB: case I_V_SX: /* short branches */ + r = get_addr (gbuf, &tptr, &t, addr); /* get addr */ + if ((r != SCPE_OK) || (t & 1) || *tptr) /* error if odd */ + return SCPE_ARG; + st = t; /* signed version */ + 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; + break; + } /* end case */ val[0] = inst; return -1; diff --git a/Interdata/id32_cpu.c b/Interdata/id32_cpu.c index 59100167..2000d743 100644 --- a/Interdata/id32_cpu.c +++ b/Interdata/id32_cpu.c @@ -19,33 +19,34 @@ 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 + 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 Interdata 32b CPU + cpu Interdata 32b CPU - 10-Mar-05 RMS Fixed bug in initial memory allocation - RMS Fixed bug in show history routine (from Mark Hittinger) - RMS Revised examine/deposit to do words rather than bytes - 18-Feb-05 RMS Fixed branches to mask new PC (from Greg Johnson) - 06-Nov-04 RMS Added =n to SHOW HISTORY - 25-Jan-04 RMS Revised for device debug support - 31-Dec-03 RMS Fixed bug in cpu_set_hist - 22-Sep-03 RMS Added additional instruction decode types - Added instruction history + 16-Aug-05 RMS Fixed C++ declaration and cast problems + 10-Mar-05 RMS Fixed bug in initial memory allocation + RMS Fixed bug in show history routine (from Mark Hittinger) + RMS Revised examine/deposit to do words rather than bytes + 18-Feb-05 RMS Fixed branches to mask new PC (from Greg Johnson) + 06-Nov-04 RMS Added =n to SHOW HISTORY + 25-Jan-04 RMS Revised for device debug support + 31-Dec-03 RMS Fixed bug in cpu_set_hist + 22-Sep-03 RMS Added additional instruction decode types + Added instruction history 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 + 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 @@ -53,32 +54,32 @@ 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - | op | R1 | R2 | register-register + | 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 + | 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) + | 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) + | 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) + | op | R1 | RX | register-memory 3 + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ (double index) | 0| 1| 0| 0| RX2 | address hi | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | address lo | @@ -86,14 +87,14 @@ 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - | op | R1 | RX | register-immediate 1 + | 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 + | op | R1 | RX | register-immediate 2 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | immediate hi | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ @@ -103,20 +104,19 @@ 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) + 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) + 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) + 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. + + 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. @@ -125,11 +125,11 @@ 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 + 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, @@ -144,103 +144,105 @@ 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 + 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 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 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 HIST_PC 0x40000000 -#define HIST_MIN 64 -#define HIST_MAX 65536 -struct InstHistory { - uint32 pc; - uint32 ir1; - uint32 ir2; - uint32 ir3; - uint32 r1; - uint32 ea; - uint32 opnd; }; +#define HIST_PC 0x40000000 +#define HIST_MIN 64 +#define HIST_MAX 65536 -#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 +typedef struct { + uint32 pc; + uint32 ir1; + uint32 ir2; + uint32 ir3; + uint32 r1; + uint32 ea; + uint32 opnd; + } InstHistory; + +#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 /* Logging */ -#define LOG_CPU_I 0x0001 /* intr/exception */ -#define LOG_CPU_C 0x0002 /* context change */ - -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 hst_p = 0; /* history pointer */ -uint32 hst_lnt = 0; /* history length */ -struct InstHistory *hst = NULL; /* instruction history */ -jmp_buf save_env; /* abort handler */ -struct BlockIO blk_io; /* block I/O status */ +#define LOG_CPU_I 0x0001 /* intr/exception */ +#define LOG_CPU_C 0x0002 /* context change */ + +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 hst_p = 0; /* history pointer */ +uint32 hst_lnt = 0; /* history length */ +InstHistory *hst = NULL; /* instruction history */ +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 int32 sim_brk_types, sim_brk_dflt, sim_brk_summ; /* breakpoint info */ +extern UNIT pic_unit, lfc_unit, pas_unit; /* timers */ extern FILE *sim_deb; uint32 ReadB (uint32 loc, uint32 rel); @@ -276,211 +278,212 @@ 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_RXH, /* CRC12 */ - OP_RXH, /* 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_RXH, /* 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_RR, /* LDBR */ - OP_RR, /* 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_RXB, /* LDB */ - OP_RXB, /* 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_RXH | 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 */ - + 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_RXH, /* CRC12 */ + OP_RXH, /* 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_RXH, /* 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_RR, /* LDBR */ + OP_RR, /* 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_RXB, /* LDB */ + OP_RXB, /* 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_RXH | 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 + 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 }; @@ -488,120 +491,127 @@ 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 (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 } }; + { 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 (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 }, - { MTAB_XTD|MTAB_VDV|MTAB_NMO|MTAB_SHP, 0, "HISTORY", "HISTORY", - &cpu_set_hist, &cpu_show_hist }, - { 0 } }; + { 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 }, + { MTAB_XTD|MTAB_VDV|MTAB_NMO|MTAB_SHP, 0, "HISTORY", "HISTORY", + &cpu_set_hist, &cpu_show_hist }, + { 0 } + }; DEBTAB cpu_deb[] = { - { "INTEXC", LOG_CPU_I }, - { "CONTEXT", LOG_CPU_C }, - { NULL, 0 } }; + { "INTEXC", LOG_CPU_I }, + { "CONTEXT", LOG_CPU_C }, + { NULL, 0 } + }; DEVICE cpu_dev = { - "CPU", &cpu_unit, cpu_reg, cpu_mod, - 1, 16, 20, 2, 16, 16, - &cpu_ex, &cpu_dep, &cpu_reset, - NULL, NULL, NULL, - &cpu_dib, DEV_DEBUG, 0, - cpu_deb, NULL, NULL }; - + "CPU", &cpu_unit, cpu_reg, cpu_mod, + 1, 16, 20, 2, 16, 16, + &cpu_ex, &cpu_dep, &cpu_reset, + NULL, NULL, NULL, + &cpu_dib, DEV_DEBUG, 0, + cpu_deb, NULL, NULL + }; + t_stat sim_instr (void) { -volatile uint32 cc; /* set before setjmp */ -t_stat reason; /* set after setjmp */ +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 (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 */ + 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 @@ -614,897 +624,961 @@ reason = 0; 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 */ - +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; -uint32 ir1, ir2, ir3, ityp; -int32 sr, st; +while (reason == 0) { /* loop until halted */ -if (sim_interval <= 0) { /* check clock queue */ - if (reason = sim_process_event ()) break; - int_eval (); } + uint32 dev, drom, opnd, inc, lim, bufa; + uint32 op, r1, r1p1, r2, rx2, ea; + uint32 mpy, mpc, dvr; + uint32 i, rslt, rlo, t; + uint32 ir1, ir2, ir3, ityp; + int32 sr, st; -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 (sim_interval <= 0) { /* check clock queue */ + if (reason = sim_process_event ()) break; + int_eval (); + } - 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) { /* 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_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 (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 (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; } + 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 */ + } - 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; } + if (sim_brk_summ && sim_brk_test (PC, SWMASK ('E'))) { /* breakpoint? */ + reason = STOP_IBKPT; /* stop simulation */ + break; + } -sim_interval = sim_interval - 1; + sim_interval = sim_interval - 1; -ir1 = ReadH (oPC = PC, VE); /* fetch instr */ -op = (ir1 >> 8) & 0xFF; /* extract op,R1,R2 */ -r1 = (ir1 >> 4) & 0xF; -r2 = ir1 & 0xF; -drom = decrom[op]; /* get decode flags */ -ityp = drom & OP_MASK; /* instruction type */ + ir1 = ReadH (oPC = PC, VE); /* fetch instr */ + op = (ir1 >> 8) & 0xFF; /* extract op,R1,R2 */ + r1 = (ir1 >> 4) & 0xF; + r2 = ir1 & 0xF; + drom = decrom[op]; /* get decode flags */ + ityp = drom & OP_MASK; /* instruction type */ -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; } + 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 (ityp) { /* decode instruction */ -case OP_NO: /* no operand */ - opnd = r2; /* assume short */ - PC = (PC + 2) & VAMASK; /* increment PC */ - break; + switch (ityp) { /* decode instruction */ -case OP_RR: /* reg-reg */ - opnd = R[r2]; /* ea/operand is R2 */ - PC = (PC + 2) & VAMASK; /* increment PC */ - break; + case OP_NO: /* no operand */ + opnd = r2; /* assume short */ + PC = (PC + 2) & VAMASK; /* increment PC */ + break; -case OP_RI1: /* reg-imm 1 */ - ir2 = ReadH ((PC + 2) & VAMASK, VE); /* fetch immed */ - opnd = SEXT16 (ir2); /* sign extend */ - if (r2) opnd = (opnd + R[r2]) & DMASK32; /* index calculation */ - PC = (PC + 4) & VAMASK; /* increment PC */ - break; + case OP_RR: /* reg-reg */ + opnd = R[r2]; /* ea/operand is R2 */ + PC = (PC + 2) & VAMASK; /* increment PC */ + break; -case OP_RI2: /* reg-imm 2 */ - ir2 = ReadH ((PC + 2) & VAMASK, VE); /* fetch imm hi */ - ir3 = ReadH ((PC + 4) & VAMASK, VE); /* fetch imm lo */ - opnd = (ir2 << 16) | ir3; /* 32b immediate */ - if (r2) opnd = (opnd + R[r2]) & DMASK32; /* index calculation */ - PC = (PC + 6) & VAMASK; /* increment PC */ - break; + case OP_RI1: /* reg-imm 1 */ + ir2 = ReadH ((PC + 2) & VAMASK, VE); /* fetch immed */ + opnd = SEXT16 (ir2); /* sign extend */ + if (r2) opnd = (opnd + R[r2]) & DMASK32; /* index calculation */ + PC = (PC + 4) & VAMASK; /* increment PC */ + break; -case OP_RX: case OP_RXB: case OP_RXH: case OP_RXF: /* reg-mem */ - ir2 = ReadH ((PC + 2) & VAMASK, VE); /* fetch addr */ - if ((ir2 & 0xC000) == 0) { /* displacement? */ - PC = (PC + 4) & VAMASK; /* increment PC */ - ea = ir2; } /* abs 14b displ */ - else if (ir2 & 0x8000) { /* relative? */ - PC = (PC + 4) & VAMASK; /* increment PC */ - ea = PC + SEXT15 (ir2); } /* add to incr PC */ - else { /* absolute */ - rx2 = (ir2 >> 8) & 0xF; /* get second index */ - ea = (ir2 & 0xFF) << 16; /* shift to place */ - ir3 = ReadH ((PC + 4) & VAMASK, VE); /* fetch addr lo */ - ea = ea | ir3; /* 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 (ityp == OP_RXF) opnd = ReadF (ea, VR); /* get fw operand? */ - else if (ityp == OP_RXH) { /* get hw operand? */ - t = ReadH (ea, VR); /* read halfword */ - opnd = SEXT16 (t); } /* sign extend */ - else if (ityp == OP_RXB) opnd = ReadB (ea, VR); /* get byte opnd? */ - else opnd = ea; /* just address */ - break; + case OP_RI2: /* reg-imm 2 */ + ir2 = ReadH ((PC + 2) & VAMASK, VE); /* fetch imm hi */ + ir3 = ReadH ((PC + 4) & VAMASK, VE); /* fetch imm lo */ + opnd = (ir2 << 16) | ir3; /* 32b immediate */ + if (r2) opnd = (opnd + R[r2]) & DMASK32; /* index calculation */ + PC = (PC + 6) & VAMASK; /* increment PC */ + break; -default: - return SCPE_IERR; } + case OP_RX: case OP_RXB: case OP_RXH: case OP_RXF: /* reg-mem */ + ir2 = ReadH ((PC + 2) & VAMASK, VE); /* fetch addr */ + if ((ir2 & 0xC000) == 0) { /* displacement? */ + PC = (PC + 4) & VAMASK; /* increment PC */ + ea = ir2; /* abs 14b displ */ + } + else if (ir2 & 0x8000) { /* relative? */ + PC = (PC + 4) & VAMASK; /* increment PC */ + ea = PC + SEXT15 (ir2); /* add to incr PC */ + } + else { /* absolute */ + rx2 = (ir2 >> 8) & 0xF; /* get second index */ + ea = (ir2 & 0xFF) << 16; /* shift to place */ + ir3 = ReadH ((PC + 4) & VAMASK, VE); /* fetch addr lo */ + ea = ea | ir3; /* 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 (ityp == OP_RXF) opnd = ReadF (ea, VR); /* get fw operand? */ + else if (ityp == OP_RXH) { /* get hw operand? */ + t = ReadH (ea, VR); /* read halfword */ + opnd = SEXT16 (t); /* sign extend */ + } + else if (ityp == OP_RXB) opnd = ReadB (ea, VR); /* get byte opnd? */ + else opnd = ea; /* just address */ + break; + + default: + return SCPE_IERR; + } + + if (hst_lnt) { /* instruction history? */ + hst[hst_p].pc = oPC | HIST_PC; /* save decode state */ + hst[hst_p].ir1 = ir1; + hst[hst_p].ir2 = ir2; + hst[hst_p].ir3 = ir3; + hst[hst_p].r1 = R[r1]; + hst[hst_p].ea = ea; + hst[hst_p].opnd = opnd; + hst_p = hst_p + 1; + if (hst_p >= hst_lnt) hst_p = 0; + } + if (qevent & EV_MAC) continue; /* MAC abort on fetch? */ + switch (op) { /* case on opcode */ -if (hst_lnt) { /* instruction history? */ - hst[hst_p].pc = oPC | HIST_PC; /* save decode state */ - hst[hst_p].ir1 = ir1; - hst[hst_p].ir2 = ir2; - hst[hst_p].ir3 = ir3; - hst[hst_p].r1 = R[r1]; - hst[hst_p].ea = ea; - hst[hst_p].opnd = opnd; - hst_p = hst_p + 1; - if (hst_p >= hst_lnt) hst_p = 0; } -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 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 - RXH */ - R[r1] = opnd & DMASK16; /* get op, zero ext */ - CC_GL_32 (R[r1]); /* set G, L */ - break; + case 0x73: /* LHL - RXH */ + R[r1] = opnd & DMASK16; /* 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 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 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 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 0x40: /* STH - RX */ + WriteH (ea, R[r1], VW); /* store register */ + break; -case 0x50: /* ST - RX */ - WriteF (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 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 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 0xE0: /* TS - RXH */ + CC_GL_16 (opnd); /* set cc's */ + WriteH (ea, opnd | SIGN16, VW); /* set MSB */ + break; -case 0x93: /* LDBR - RR */ -case 0xD3: /* LDB - RXB */ - R[r1] = opnd & DMASK8; /* load byte */ - break; + case 0x93: /* LDBR - RR */ + case 0xD3: /* LDB - RXB */ + R[r1] = opnd & DMASK8; /* 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 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 - RR */ - R[r1] = ((opnd >> 16) & DMASK16) | ((opnd & DMASK16) << 16); - break; + case 0x34: /* EXHR - RR */ + R[r1] = ((opnd >> 16) & DMASK16) | ((opnd & DMASK16) << 16); + break; + + case 0x94: /* EXBR - RR */ + R[r1] = (R[r1] & ~DMASK16) | + ((opnd >> 8) & DMASK8) | ((opnd & DMASK8) << 8); + break; -case 0x94: /* EXBR - RR */ - R[r1] = (R[r1] & ~DMASK16) | - ((opnd >> 8) & DMASK8) | ((opnd & 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 & VAMASK; /* branch */ - break; + case 0x01: /* BALR - RR */ + case 0x41: /* BAL - RX */ + PCQ_ENTRY; /* save old PC */ + R[r1] = PC; /* save cur PC */ + PC = opnd & VAMASK; /* branch */ + break; -case 0x02: /* BTCR - RR */ -case 0x42: /* BTC - RX */ - if (cc & r1) { /* test CC's */ - PCQ_ENTRY; /* branch if true */ - PC = opnd & VAMASK; } - break; + case 0x02: /* BTCR - RR */ + case 0x42: /* BTC - RX */ + if (cc & r1) { /* test CC's */ + PCQ_ENTRY; /* branch if true */ + PC = opnd & VAMASK; + } + break; -case 0x20: /* BTBS - NO */ - if (cc & r1) { /* test CC's */ - PCQ_ENTRY; /* branch if true */ - PC = (oPC - r2 - r2) & VAMASK; } - 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 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 & VAMASK; } - break; + case 0x03: /* BFCR - RR */ + case 0x43: /* BFC - RX */ + if ((cc & r1) == 0) { /* test CC's */ + PCQ_ENTRY; /* branch if false */ + PC = opnd & VAMASK; + } + break; -case 0x22: /* BFBS - NO */ - if ((cc & r1) == 0) { /* test CC's */ - PCQ_ENTRY; /* branch if false */ - PC = (oPC - r2 - r2) & VAMASK; } - 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 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 = opnd & 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 = opnd & VAMASK; + } + 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) & DMASK32; /* R1 = R1 + inc */ + if (R[r1] <= lim) { /* if R1 <= lim */ + PCQ_ENTRY; /* branch */ + PC = opnd & VAMASK; + } + 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) & DMASK32; /* R1 = R1 + inc */ - if (R[r1] <= lim) { /* if R1 <= lim */ - PCQ_ENTRY; /* branch */ - PC = opnd & VAMASK; } - 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 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 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 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 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 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 - RXB */ - 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 0xD4: /* CLB - RXB */ + 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; -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 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 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 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 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 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 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 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 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 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; -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 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 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 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; -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 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 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 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 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 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 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 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 0x0D: /* DHR - RR */ + case 0x4D: /* DH - RXH */ + opnd = opnd & DMASK16; /* force HW opnd */ + if ((opnd == 0) || /* div by zero? */ + ((R[r1] == 0x80000000) && (opnd = 0xFFFF))) { + if (PSW & PSW_AFI) /* div fault enabled? */ + cc = exception (AFIPSW, cc, 0); /* exception */ + break; + } + r1p1 = (r1 + 1) & 0xF; + st = SEXT32 (R[r1]) / SEXT16 (opnd); /* quotient */ + sr = SEXT32 (R[r1]) % SEXT16 (opnd); /* remainder */ + if ((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; -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 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 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 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 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 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 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 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 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 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 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 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 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; -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 (DEBUG_PRI (cpu_dev, LOG_CPU_C)) fprintf (sim_deb, - ">>SVC: oPC = %X, oPSW = %X, nPC = %X, nPSW = %X\n", - pcq[pcq_p], t, PC, PSW); - break; + + 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 (DEBUG_PRI (cpu_dev, LOG_CPU_C)) fprintf (sim_deb, + ">>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 0xE2: /* SINT - RI1 */ + dev = opnd & DEV_MAX; /* get dev */ + cc = int_auto (dev, cc); /* auto int */ + int_eval (); + break; -case 0xE3: /* SCP - RXH */ - opnd = opnd & DMASK16; /* 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 0xE3: /* SCP - RXH */ + opnd = opnd & DMASK16; /* 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 (DEBUG_PRI (cpu_dev, LOG_CPU_C)) fprintf (sim_deb, - ">>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 0x18: /* LPSWR - RR */ + PCQ_ENTRY; /* effective branch */ + PC = R[(r2 + 1) & 0xF] & VAMASK; /* new PC (old reg set) */ + if (DEBUG_PRI (cpu_dev, LOG_CPU_C)) fprintf (sim_deb, + ">>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 (DEBUG_PRI (cpu_dev, LOG_CPU_C)) fprintf (sim_deb, - ">>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 0xC2: /* LPSW - RXF */ + PCQ_ENTRY; /* effective branch */ + PC = ReadF ((ea + 4) & VAMASK, VR) & VAMASK; /* new PC */ + if (DEBUG_PRI (cpu_dev, LOG_CPU_C)) fprintf (sim_deb, + ">>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 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 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 0x66: /* RTL - RX */ + case 0x67: /* RBL - RX */ + cc = remfmq (ea, r1, op & 1); /* rem from q */ + break; -case 0x5E: /* CRC12 - RXH */ - opnd = opnd & DMASK16; /* 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 0x5E: /* CRC12 - RXH */ + opnd = opnd & DMASK16; /* 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 = opnd & DMASK16; /* 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 0x5F: /* CRC16 - RXH */ + opnd = opnd & DMASK16; /* 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; -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 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 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 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 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 - 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; - 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 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; + 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 - 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, VW); /* RX or RR? */ + else R[r2] = t & DMASK8; + cc = t & 0xF; + int_eval (); /* re-eval intr */ + break; -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, 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 @@ -1513,78 +1587,85 @@ case 0xDD: /* SS - RX */ 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 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 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 */ + 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 */ +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 */ +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? */ +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 */ +if (PSW & PSW_EXI) SET_ENB (v_DS); /* enable/disable */ +else CLR_ENB (v_DS); /* console intr */ return PSW & CC_MASK; } @@ -1592,33 +1673,37 @@ return PSW & CC_MASK; uint32 exception (uint32 loc, uint32 cc, uint32 flg) { -int32 oldPSW = BUILD_PSW (cc); /* save old PSW */ -int32 oldPC = PC; /* save old PC */ +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 */ +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 (DEBUG_PRI (cpu_dev, LOG_CPU_I)) fprintf (sim_deb, - ">>Exc %X: oPC = %X, oPSW = %X, nPC = %X, nPSW = %X\n", - loc, oldPC, oldPSW, PC, PSW | cc | flg); -return cc | flg; /* return CC */ + ">>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 */ +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; } +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; } @@ -1628,21 +1713,24 @@ 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 */ +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; } @@ -1653,26 +1741,29 @@ 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 */ +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) @@ -1682,110 +1773,132 @@ 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 # */ +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 (DEBUG_PRI (cpu_dev, LOG_CPU_I)) fprintf (sim_deb, - ">>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 */ + ">>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) @@ -1793,88 +1906,102 @@ 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; } + + 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 */ +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 */ +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) - IOReadH read halfword (IO) - IOWriteH write halfword (IO) + 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 rel) @@ -1882,14 +2009,18 @@ 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]; } +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; } @@ -1897,14 +2028,18 @@ 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]; } +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; } @@ -1912,14 +2047,18 @@ 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]; } +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; } @@ -1929,17 +2068,20 @@ 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 ((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); + (M[pa >> 2] & ~(DMASK8 << sc)) | (val << sc); return; } @@ -1948,19 +2090,22 @@ 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 ((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)); + ((M[pa >> 2] & ~DMASK16) | val): + ((M[pa >> 2] & DMASK16) | (val << 16)); return; } @@ -1970,17 +2115,21 @@ 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 */ + 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; } @@ -2014,22 +2163,22 @@ val = val & DMASK16; M[loc >> 2] = (M[loc >> 2] & ~(DMASK16 << 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 */ +qevent = 0; /* no events */ +mac_sta = 0; /* clear MAC */ +newPSW (0); /* PSW = 0 */ set_r_display (R); -DR = 0; /* clear display */ +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 >> 2, sizeof (uint32)); +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 = (uint32 *) calloc (MAXMEMSIZE32 >> 2, sizeof (uint32)); if (M == NULL) return SCPE_MEM; -pcq_r = find_reg ("PCQ", NULL, dptr); /* init PCQ */ +pcq_r = find_reg ("PCQ", NULL, dptr); /* init PCQ */ if (pcq_r) pcq_r->qptr = 0; else return SCPE_IERR; return SCPE_OK; @@ -2040,8 +2189,9 @@ return SCPE_OK; 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; } + 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 = IOReadH (addr); return SCPE_OK; @@ -2052,8 +2202,9 @@ return SCPE_OK; 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; } + int32 cc = RelocT (addr, MAC_BASE, P, &addr); + if (cc & (CC_C | CC_V)) return SCPE_NXM; + } if (addr >= MEMSIZE) return SCPE_NXM; IOWriteH (addr, val); return SCPE_OK; @@ -2067,10 +2218,10 @@ uint32 mc = 0; uint32 i; if ((val <= 0) || (val > MAXMEMSIZE32) || ((val & 0xFFFF) != 0)) - return SCPE_ARG; + 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; + return SCPE_OK; MEMSIZE = val; for (i = MEMSIZE; i < MAXMEMSIZE32; i = i + 4) M[i >> 2] = 0; return SCPE_OK; @@ -2106,20 +2257,23 @@ uint32 i, lnt; t_stat r; if (cptr == NULL) { - for (i = 0; i < hst_lnt; i++) hst[i].pc = 0; - hst_p = 0; - return SCPE_OK; } + for (i = 0; i < hst_lnt; i++) hst[i].pc = 0; + hst_p = 0; + return SCPE_OK; + } lnt = (uint32) get_uint (cptr, 10, HIST_MAX, &r); if ((r != SCPE_OK) || (lnt && (lnt < HIST_MIN))) return SCPE_ARG; hst_p = 0; if (hst_lnt) { - free (hst); - hst_lnt = 0; - hst = NULL; } + free (hst); + hst_lnt = 0; + hst = NULL; + } if (lnt) { - hst = calloc (sizeof (struct InstHistory), lnt); - if (hst == NULL) return SCPE_MEM; - hst_lnt = lnt; } + hst = (InstHistory *) calloc (lnt, sizeof (InstHistory)); + if (hst == NULL) return SCPE_MEM; + hst_lnt = lnt; + } return SCPE_OK; } @@ -2131,32 +2285,33 @@ int32 op, k, di, lnt; char *cptr = (char *) desc; t_value sim_eval[3]; t_stat r; -struct InstHistory *h; +InstHistory *h; extern t_stat fprint_sym (FILE *ofile, t_addr addr, t_value *val, - UNIT *uptr, int32 sw); + UNIT *uptr, int32 sw); -if (hst_lnt == 0) return SCPE_NOFNC; /* enabled? */ +if (hst_lnt == 0) return SCPE_NOFNC; /* enabled? */ if (cptr) { - lnt = (int32) get_uint (cptr, 10, hst_lnt, &r); - if ((r != SCPE_OK) || (lnt == 0)) return SCPE_ARG; } + lnt = (int32) get_uint (cptr, 10, hst_lnt, &r); + if ((r != SCPE_OK) || (lnt == 0)) return SCPE_ARG; + } else lnt = hst_lnt; -di = hst_p - lnt; /* work forward */ +di = hst_p - lnt; /* work forward */ if (di < 0) di = di + hst_lnt; fprintf (st, "PC r1 operand ea IR\n\n"); -for (k = 0; k < lnt; k++) { /* print specified */ - h = &hst[(di++) % hst_lnt]; /* entry pointer */ - if (h->pc & HIST_PC) { /* instruction? */ - fprintf (st, "%06X %08X %08X ", h->pc & VAMASK32, h->r1, h->opnd); - op = (h->ir1 >> 8) & 0xFF; - if (OP_TYPE (op) >= OP_RX) fprintf (st, "%06X ", h->ea); - else fprintf (st, " "); - sim_eval[0] = h->ir1; - sim_eval[1] = h->ir2; - sim_eval[2] = h->ir3; - if ((fprint_sym (st, h->pc & VAMASK32, sim_eval, &cpu_unit, SWMASK ('M'))) > 0) - fprintf (st, "(undefined) %04X", h->ir1); - fputc ('\n', st); /* end line */ - } /* end if instruction */ - } /* end for */ +for (k = 0; k < lnt; k++) { /* print specified */ + h = &hst[(di++) % hst_lnt]; /* entry pointer */ + if (h->pc & HIST_PC) { /* instruction? */ + fprintf (st, "%06X %08X %08X ", h->pc & VAMASK32, h->r1, h->opnd); + op = (h->ir1 >> 8) & 0xFF; + if (OP_TYPE (op) >= OP_RX) fprintf (st, "%06X ", h->ea); + else fprintf (st, " "); + sim_eval[0] = h->ir1; + sim_eval[1] = h->ir2; + sim_eval[2] = h->ir3; + if ((fprint_sym (st, h->pc & VAMASK32, sim_eval, &cpu_unit, SWMASK ('M'))) > 0) + fprintf (st, "(undefined) %04X", h->ir1); + fputc ('\n', st); /* end line */ + } /* end if instruction */ + } /* end for */ return SCPE_OK; } diff --git a/Interdata/id32_dboot.c b/Interdata/id32_dboot.c index 951dbd43..443e8549 100644 --- a/Interdata/id32_dboot.c +++ b/Interdata/id32_dboot.c @@ -1,6 +1,6 @@ /* id32_dboot.c: Interdata 32b simulator disk bootstrap - Copyright (c) 2000-2004, Robert M. Supnik + Copyright (c) 2000-2005, 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"), @@ -19,18 +19,18 @@ 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 + 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 + 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)) +#define DBOOT_BEG 0x1000 +#define DBOOT_START 0x100E +#define DBOOT_LEN (sizeof (dboot_rom) / sizeof (uint8)) /* Transcribed from 32b Bootstrap Loader, 03-074N81R03A13 */ @@ -252,35 +252,36 @@ static uint8 dboot_rom[] = { 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) + 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; -}; + 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 } }; + { "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) { @@ -290,27 +291,29 @@ 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 */ +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 ((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 */ +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_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 index d26541bc..01e3a5f6 100644 --- a/Interdata/id32_sys.c +++ b/Interdata/id32_sys.c @@ -1,6 +1,6 @@ /* id32_sys.c: Interdata 32b simulator interface - Copyright (c) 2000-2004, Robert M. Supnik + Copyright (c) 2000-2005, 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"), @@ -19,21 +19,21 @@ 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 + 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. - 02-Jul-04 RMS Fixed missing type in declaration - 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 + 02-Jul-04 RMS Fixed missing type in declaration + 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)) +#define MSK_SBF 0x0100 +#define SEXT15(x) (((x) & 0x4000)? ((x) | ~0x3FFF): ((x) & 0x3FFF)) extern DEVICE cpu_dev; extern DEVICE sch_dev; @@ -55,12 +55,12 @@ extern t_stat 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 + 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"; @@ -70,29 +70,31 @@ 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 }; + &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" }; + "Unknown error", + "Reserved instruction", + "HALT instruction", + "Breakpoint", + "Wait state", + "Runaway VFU" + }; /* Binary loader -- load carriage control tape Binary dump -- paper tape dump */ @@ -102,60 +104,63 @@ 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 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 */ +#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 }; + 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 }; + 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 }; + R_X + }; static const char *opcode[] = { "BER", "BNER","BZR", "BNZR", @@ -220,7 +225,8 @@ static const char *opcode[] = { "TI", "NI", "CLI", "OI", "XI", "LI", "CI", "AI", "SI", -NULL }; +NULL +}; static const uint32 opc_val[] = { 0x0330+I_R, 0x0230+I_R, 0x0330+I_R, 0x0230+I_R, @@ -285,25 +291,28 @@ static const uint32 opc_val[] = { 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 }; - +0xFFFF +}; + /* Print an RX specifier */ t_stat fprint_addr (FILE *of, t_addr addr, uint32 rx, uint32 ea1, - uint32 ea2) + uint32 ea2) { uint32 rx2; -if ((ea1 & 0xC000) == 0) { /* RX1 */ - fprintf (of, "%-X", ea1); - if (rx) fprintf (of, "(R%d)", rx); - return -3; } -if (ea1 & 0x8000) { /* RX2 */ - ea1 = addr + 4 + SEXT15 (ea1); - fprintf (of, "%-X", ea1 & VAMASK32); - if (rx) fprintf (of, "(R%d)", rx); - return -3; } -rx2 = (ea1 >> 8) & 0xF; /* RX3 */ +if ((ea1 & 0xC000) == 0) { /* RX1 */ + fprintf (of, "%-X", ea1); + if (rx) fprintf (of, "(R%d)", rx); + return -3; + } +if (ea1 & 0x8000) { /* RX2 */ + ea1 = addr + 4 + SEXT15 (ea1); + fprintf (of, "%-X", ea1 & VAMASK32); + if (rx) fprintf (of, "(R%d)", rx); + return -3; + } +rx2 = (ea1 >> 8) & 0xF; /* RX3 */ 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); @@ -313,52 +322,57 @@ return -5; /* Symbolic decode Inputs: - *of = output stream - addr = current PC - *val = values to decode - *uptr = pointer to unit - sw = switches + *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 + 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) + UNIT *uptr, int32 sw) { int32 c1, c2, rdx; t_stat r; DEVICE *dptr; -if (uptr == NULL) uptr = &cpu_unit; /* anon = CPU */ -else if (uptr != &cpu_unit) return SCPE_ARG; /* only for CPU */ -dptr = find_dev_from_unit (uptr); /* find dev */ +if (uptr == NULL) uptr = &cpu_unit; /* anon = CPU */ +else if (uptr != &cpu_unit) return SCPE_ARG; /* only for CPU */ +dptr = find_dev_from_unit (uptr); /* find dev */ if (dptr == NULL) return SCPE_IERR; -if (sw & SWMASK ('D')) rdx = 10; /* get radix */ +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; -if (sw & SWMASK ('A')) { /* ASCII char? */ - c1 = (val[0] >> ((addr & 1)? 0: 8)) & 0x7F; /* get byte */ - fprintf (of, (c1 < 0x20)? "<%02X>": "%c", c1); - return 0; } -if (sw & SWMASK ('B')) { /* byte? */ - c1 = (val[0] >> ((addr & 1)? 0: 8)) & 0xFF; /* get byte */ - fprint_val (of, c1, rdx, 8, PV_RZRO); - return 0; } -if (sw & SWMASK ('C')) { /* string? */ - c1 = (val[0] >> 8) & 0x7F; - c2 = val[0] & 0x7F; - fprintf (of, (c1 < 0x20)? "<%02X>": "%c", c1); - fprintf (of, (c2 < 0x20)? "<%02X>": "%c", c2); - return -1; } -if (sw & SWMASK ('H')) { /* halfword? */ - fprint_val (of, val[0], rdx, 16, PV_RZRO); - return -1; } -if (sw & SWMASK ('M')) { /* inst format? */ - r = fprint_sym_m (of, addr, val); /* decode inst */ - if (r <= 0) return r; } +if (sw & SWMASK ('A')) { /* ASCII char? */ + c1 = (val[0] >> ((addr & 1)? 0: 8)) & 0x7F; /* get byte */ + fprintf (of, (c1 < 0x20)? "<%02X>": "%c", c1); + return 0; + } +if (sw & SWMASK ('B')) { /* byte? */ + c1 = (val[0] >> ((addr & 1)? 0: 8)) & 0xFF; /* get byte */ + fprint_val (of, c1, rdx, 8, PV_RZRO); + return 0; + } +if (sw & SWMASK ('C')) { /* string? */ + c1 = (val[0] >> 8) & 0x7F; + c2 = val[0] & 0x7F; + fprintf (of, (c1 < 0x20)? "<%02X>": "%c", c1); + fprintf (of, (c2 < 0x20)? "<%02X>": "%c", c2); + return -1; + } +if (sw & SWMASK ('H')) { /* halfword? */ + fprint_val (of, val[0], rdx, 16, PV_RZRO); + return -1; + } +if (sw & SWMASK ('M')) { /* inst format? */ + r = fprint_sym_m (of, addr, val); /* decode inst */ + if (r <= 0) return r; + } fprint_val (of, (val[0] << 16) | val[1], rdx, 32, PV_RZRO); return -3; @@ -367,13 +381,13 @@ return -3; /* Symbolic decode for -m Inputs: - of = output stream - addr = current PC - *val = values to decode - cf = true if parsing for CPU + 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 + 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) @@ -383,78 +397,89 @@ uint32 i, j, inst, r1, r2, ea1, ea2; inst = val[0]; ea1 = val[1]; ea2 = val[2]; -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 */ - fprintf (of, "%-X", ((inst & MSK_SBF)? - (addr + r2 + r2): (addr - 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); - 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); - } /* end case */ - return SCPE_IERR; - } /* end if */ - } /* end for */ -return SCPE_ARG; /* no match */ +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 */ + fprintf (of, "%-X", ((inst & MSK_SBF)? + (addr + r2 + r2): (addr - 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); + + 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); + } /* end case */ + 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 + *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 + 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 == '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; } + 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; @@ -466,12 +491,12 @@ return reg; /* Immediate Inputs: - *cptr = pointer to input string - *imm = pointer to output value - *inst = pointer to instruction - max = max value + *cptr = pointer to input string + *imm = pointer to output value + *inst = pointer to instruction + max = max value Outputs: - sta = status + sta = status */ t_stat get_imm (char *cptr, uint32 *imm, uint32 *inst, uint32 max) @@ -480,13 +505,14 @@ char *tptr; int32 idx; errno = 0; -*imm = strtoul (cptr, &tptr, 16); /* get immed */ +*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 == '(') { /* 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; } @@ -494,33 +520,35 @@ return SCPE_OK; /* Address Inputs: - *cptr = pointer to input string - **tptr = pointer to moved pointer - *ea = effective address - addr = base address + *cptr = pointer to input string + **tptr = pointer to moved pointer + *ea = effective address + addr = base address Outputs: - status = SCPE_OK if ok, else error code + status = SCPE_OK if ok, else error code */ t_stat get_addr (char *cptr, char **tptr, t_addr *ea, t_addr addr) { int32 sign = 1; -if (*cptr == '.') { /* relative? */ - cptr++; - *ea = addr; - if (*cptr == '+') cptr++; /* .+? */ - else if (*cptr == '-') { /* .-? */ - sign = -1; - cptr++; } - else return SCPE_OK; } +if (*cptr == '.') { /* relative? */ + cptr++; + *ea = addr; + if (*cptr == '+') cptr++; /* .+? */ + else if (*cptr == '-') { /* .-? */ + sign = -1; + cptr++; + } + else return SCPE_OK; + } else *ea = 0; errno = 0; *ea = *ea + (sign * ((int32) strtoul (cptr, tptr, 16))); if (errno || (cptr == *tptr)) return SCPE_ARG; return SCPE_OK; } - + /* Symbolic input */ t_stat parse_sym (char *cptr, t_addr addr, UNIT *uptr, t_value *val, int32 sw) @@ -529,38 +557,42 @@ int32 by, rdx, num; t_stat r; DEVICE *dptr; -if (uptr == NULL) uptr = &cpu_unit; /* anon = CPU */ -else if (uptr != &cpu_unit) return SCPE_ARG; /* CPU only */ -dptr = find_dev_from_unit (uptr); /* find dev */ +if (uptr == NULL) uptr = &cpu_unit; /* anon = CPU */ +else if (uptr != &cpu_unit) return SCPE_ARG; /* CPU only */ +dptr = find_dev_from_unit (uptr); /* find dev */ if (dptr == NULL) return SCPE_IERR; -if (sw & SWMASK ('D')) rdx = 10; /* get radix */ +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; if ((sw & SWMASK ('A')) || ((*cptr == '\'') && cptr++)) { /* ASCII char? */ - if (cptr[0] == 0) return SCPE_ARG; /* must have 1 char */ - if (addr & 1) val[0] = (val[0] & ~0xFF) | ((t_value) cptr[0]); - else val[0] = (val[0] & 0xFF) | (((t_value) cptr[0]) << 8); - return 0; } -if (sw & SWMASK ('B')) { /* byte? */ - by = get_uint (cptr, rdx, DMASK8, &r); /* get byte */ - if (r != SCPE_OK) return SCPE_ARG; - if (addr & 1) val[0] = (val[0] & ~0xFF) | by; - else val[0] = (val[0] & 0xFF) | (by << 8); - return 0; } + if (cptr[0] == 0) return SCPE_ARG; /* must have 1 char */ + if (addr & 1) val[0] = (val[0] & ~0xFF) | ((t_value) cptr[0]); + else val[0] = (val[0] & 0xFF) | (((t_value) cptr[0]) << 8); + return 0; + } +if (sw & SWMASK ('B')) { /* byte? */ + by = get_uint (cptr, rdx, DMASK8, &r); /* get byte */ + if (r != SCPE_OK) return SCPE_ARG; + if (addr & 1) val[0] = (val[0] & ~0xFF) | by; + else val[0] = (val[0] & 0xFF) | (by << 8); + return 0; + } if ((sw & SWMASK ('C')) || ((*cptr == '"') && cptr++)) { /* ASCII chars? */ - if (cptr[0] == 0) return SCPE_ARG; /* must have 1 char */ - val[0] = ((t_value) cptr[0] << 8) | (t_value) cptr[1]; - return -1; } -if (sw & SWMASK ('H')) { /* halfword? */ - val[0] = (int32) get_uint (cptr, rdx, DMASK16, &r); /* get number */ - if (r != SCPE_OK) return r; - return -1; } + if (cptr[0] == 0) return SCPE_ARG; /* must have 1 char */ + val[0] = ((t_value) cptr[0] << 8) | (t_value) cptr[1]; + return -1; + } +if (sw & SWMASK ('H')) { /* halfword? */ + val[0] = (int32) get_uint (cptr, rdx, DMASK16, &r); /* get number */ + if (r != SCPE_OK) return r; + return -1; + } -r = parse_sym_m (cptr, addr, val); /* try to parse inst */ +r = parse_sym_m (cptr, addr, val); /* try to parse inst */ if (r <= 0) return r; -num = (int32) get_uint (cptr, rdx, DMASK32, &r); /* get number */ +num = (int32) get_uint (cptr, rdx, DMASK32, &r); /* get number */ if (r != SCPE_OK) return r; val[0] = (num >> 16) & DMASK16; val[1] = num & DMASK16; @@ -570,13 +602,13 @@ return -3; /* Symbolic input for -m Inputs: - *cptr = pointer to input string - addr = current PC - *val = pointer to output values - cf = true if parsing for CPU + *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 + status = > 0 error code + <= 0 -number of extra words */ t_stat parse_sym_m (char *cptr, t_addr addr, t_value *val) @@ -587,91 +619,97 @@ t_stat r; char *tptr, gbuf[CBUFSIZE]; vp = 0; -cptr = get_glyph (cptr, gbuf, 0); /* get opcode */ +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 */ +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 */ +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_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, addr); /* 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; - val[0] = inst; /* store inst */ - if (rx2 == 0) { /* no 2nd? */ - if (t < 0x4000) { /* RX1? */ - val[1] = t; /* store ea */ - return -3; } - st = (t - (addr + 4)); /* displ */ - if ((st <= 0x3FFF) && (st >= -0x4000)) { /* RX2? CPU only */ - t = (st & 0x7FFF) | 0x8000; - val[1] = t; /* store displ */ - return -3; } } - t = (t & VAMASK32) | 0x40000000 | (rx2 << 24); - val[1] = (t >> 16) & DMASK16; - val[2] = t & DMASK16; - return -5; + 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, addr); /* 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; + val[0] = inst; /* store inst */ + if (rx2 == 0) { /* no 2nd? */ + if (t < 0x4000) { /* RX1? */ + val[1] = t; /* store ea */ + return -3; + } + st = (t - (addr + 4)); /* displ */ + if ((st <= 0x3FFF) && (st >= -0x4000)) { /* RX2? CPU only */ + t = (st & 0x7FFF) | 0x8000; + val[1] = t; /* store displ */ + return -3; + } + } + t = (t & VAMASK32) | 0x40000000 | (rx2 << 24); + val[1] = (t >> 16) & DMASK16; + val[2] = t & DMASK16; + return -5; -case I_V_RI: /* 16b immediate */ - r = get_imm (gbuf, &t, &inst, DMASK16); /* process imm */ - if (r != SCPE_OK) return r; - val[0] = inst; - val[1] = t; - return -3; + case I_V_RI: /* 16b immediate */ + r = get_imm (gbuf, &t, &inst, DMASK16); /* process imm */ + if (r != SCPE_OK) return r; + val[0] = inst; + val[1] = t; + return -3; -case I_V_RF: - r = get_imm (gbuf, &t, &inst, DMASK32); /* process imm */ - if (r != SCPE_OK) return r; - val[0] = inst; - val[1] = (t >> 16) & DMASK16; - val[2] = t & DMASK16; - return -5; + case I_V_RF: + r = get_imm (gbuf, &t, &inst, DMASK32); /* process imm */ + if (r != SCPE_OK) return r; + val[0] = inst; + val[1] = (t >> 16) & DMASK16; + val[2] = t & DMASK16; + return -5; -case I_V_SB: case I_V_SX: /* short branches */ - r = get_addr (gbuf, &tptr, &t, addr); /* get addr */ - if ((r != SCPE_OK) || (t & 1) || *tptr) /* error if odd */ - return SCPE_ARG; - st = t; /* signed version */ - 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; - } /* end case */ + case I_V_SB: case I_V_SX: /* short branches */ + r = get_addr (gbuf, &tptr, &t, addr); /* get addr */ + if ((r != SCPE_OK) || (t & 1) || *tptr) /* error if odd */ + return SCPE_ARG; + st = t; /* signed version */ + 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; + } /* end case */ val[0] = inst; return -1; diff --git a/Interdata/id_defs.h b/Interdata/id_defs.h index e3aadb53..4a8787aa 100644 --- a/Interdata/id_defs.h +++ b/Interdata/id_defs.h @@ -1,6 +1,6 @@ /* id_defs.h: Interdata 16b/32b simulator definitions - Copyright (c) 2000-2004, Robert M. Supnik + Copyright (c) 2000-2005, 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"), @@ -19,444 +19,444 @@ 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 + 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. - 25-Jan-04 RMS Removed local logging support - 22-Sep-03 RMS Added additional instruction decode types - 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 + 25-Jan-04 RMS Removed local logging support + 22-Sep-03 RMS Added additional instruction decode types + 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 */ +#ifndef _ID_DEFS_H_ +#define _ID_DEFS_H_ 0 + +#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 */ +#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 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) +#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) +#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) +#define ReadFReg(r) (F[(r) >> 1]) +#define WriteFReg(r,v) F[(r) >> 1] = (v) #endif /* Double precision floating point registers */ -struct dpr { - uint32 h; /* high 32b */ - uint32 l; /* low 32b */ -}; - -typedef struct dpr dpr_t; +typedef struct { + uint32 h; /* high 32b */ + uint32 l; /* low 32b */ + } dpr_t; /* Architectural constants */ -#define VAMASK16 (0xFFFF) /* 16b virt addr */ -#define VAMASK32 (0x000FFFFF) /* 32b virt addr */ +#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 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 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 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 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 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 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 */ +#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 */ +#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 */ - }; + 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 */ +#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_RXB 0x0005 /* all: reg-mem, rd BY */ -#define OP_RXH 0x0006 /* all: reg-mem, rd HW */ -#define OP_RXF 0x0007 /* 32b: reg-mem, rd FW */ -#define OP_RI2 0x0008 /* 32b: reg-imm 32b */ -#define OP_MASK 0x000F +#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_RXB 0x0005 /* all: reg-mem, rd BY */ +#define OP_RXH 0x0006 /* all: reg-mem, rd HW */ +#define OP_RXF 0x0007 /* 32b: reg-mem, rd FW */ +#define OP_RI2 0x0008 /* 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_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_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) -#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 { + 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); + } DIB; -typedef struct interdib DIB; - -#define TPL_END 0xFF /* template end */ +#define TPL_END 0xFF /* template end */ /* Device select return codes */ -#define BY 0 /* 8b only */ -#define HW 1 /* 8b/16b */ +#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 */ +#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) +#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 */ +#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 +#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 + 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 */ +#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 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 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 +#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 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 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 +#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 */ +#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 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 */ +#define IORETURN(f,v) ((f)? (v): SCPE_OK) /* stop on error */ /* Device accessible macro */ -#define DEV_ACC(d) (dev_tab[d] && !sch_blk (d)) - +#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 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) +#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 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 */ +#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 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 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 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 */ +#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)) +#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)) /* Function prototypes */ @@ -479,3 +479,5 @@ 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); + +#endif diff --git a/Interdata/id_doc.txt b/Interdata/id_doc.txt index ec1bfbcf..dafbd71f 100644 --- a/Interdata/id_doc.txt +++ b/Interdata/id_doc.txt @@ -1,7 +1,7 @@ To: Users From: Bob Supnik Subj: Interdata 16b/32b Simulator Usage -Date: 15-Mar-2005 +Date: 01-Jul-2005 COPYRIGHT NOTICE @@ -27,8 +27,8 @@ The following copyright notice applies to both the SIMH source and binary: 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 + 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. @@ -641,8 +641,7 @@ 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. +active connections. The SET PASLn DISCONNECT command disconnects line n. The controller (PAS) implements these registers: diff --git a/Interdata/id_dp.c b/Interdata/id_dp.c index 32ce8b94..8a216ee7 100644 --- a/Interdata/id_dp.c +++ b/Interdata/id_dp.c @@ -19,96 +19,96 @@ 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 + 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 + dp M46-421 2.5MB/10MB cartridge disk - 18-Mar-05 RMS Added attached test to detach routine - 25-Jan-04 RMS Revised for device debug support - 25-Apr-03 RMS Revised for extended file support - 16-Feb-03 RMS Fixed read to test transfer ok before selch operation + 18-Mar-05 RMS Added attached test to detach routine + 25-Jan-04 RMS Revised for device debug support + 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 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 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 */ +#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) +#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 */ +#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 */ +#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 */ +#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 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))) - + 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 + type #sectors/ #surfaces/ #cylinders/ + surface cylinder drive - 2315 24 2 203 - 5440 24 4 408 + 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 @@ -116,45 +116,46 @@ 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_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) +#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 */ -}; + 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 } }; - + { CYL_2315, SURF_2315, SIZE_2315 }, + { CYL_5440, SURF_5440, SIZE_5440 }, + { 0 } + }; + extern uint32 int_req[INTSZ], int_enb[INTSZ]; extern FILE *sim_deb; -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 */ -uint8 dp_tplte[(2 * DP_NUMDR) + 2]; /* fix/rmv + ctrl + end */ +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 */ +uint8 dp_tplte[(2 * DP_NUMDR) + 2]; /* fix/rmv + ctrl + end */ DEVICE dp_dev; uint32 dp (uint32 dev, uint32 op, uint32 dat); @@ -173,81 +174,85 @@ 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 + 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) } }; + { 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) }, - { HRDATA (DEVNO, dp_dib.dno, 8), REG_HRO }, - { HRDATA (SELCH, dp_dib.sch, 2), REG_HRO }, - { NULL } }; + { 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) }, + { 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 } }; + { 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 | DEV_DEBUG }; - + "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 | DEV_DEBUG + }; + /* Controller: IO routine */ uint32 dpc (uint32 dev, uint32 op, uint32 dat) @@ -256,49 +261,58 @@ 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 (DEBUG_PRS (dp_dev)) fprintf (sim_deb, - ">>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 (DEBUG_PRS (dp_dev)) fprintf (sim_deb, - ">>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; } +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 (DEBUG_PRS (dp_dev)) fprintf (sim_deb, + ">>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 (DEBUG_PRS (dp_dev)) fprintf (sim_deb, + ">>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) @@ -307,45 +321,51 @@ 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 (DEBUG_PRS (dp_dev)) fprintf (sim_deb, - ">>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 (DEBUG_PRS (dp_dev)) fprintf (sim_deb, - ">>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; } +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 (DEBUG_PRS (dp_dev)) fprintf (sim_deb, + ">>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 (DEBUG_PRS (dp_dev)) fprintf (sim_deb, + ">>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; @@ -355,60 +375,65 @@ return 0; 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 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; } +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 */ +switch (dp_cmd & 0x7) { /* case on func */ -case CMC_RCHK: /* read check */ - dp_dter (uptr, 1); /* check xfr err */ - break; + 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_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 */ + 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; + } /* end case func */ - dp_sta = dp_sta | STC_DTE; /* can't work */ - break; } - -dp_done (0); /* done */ +dp_done (0); /* done */ return SCPE_OK; } - + /* Read data sector */ t_stat dp_rds (UNIT *uptr) @@ -416,12 +441,13 @@ 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; } +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; } @@ -430,13 +456,14 @@ return SCPE_OK; t_stat dp_wds (UNIT *uptr) { for ( ; dp_bptr < DP_NUMBY; dp_bptr++) - dpxb[dp_bptr] = dp_db; /* fill with last */ + 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; } +if (ferror (uptr->fileref)) { /* error? */ + perror ("DP I/O error"); + clearerr (uptr->fileref); + dp_done (STC_DTE); + return SCPE_IOERR; + } return SCPE_OK; } @@ -445,29 +472,34 @@ return SCPE_OK; t_bool dp_dter (UNIT *uptr, uint32 first) { uint32 hd, sc, sa; -uint32 dtype = GET_DTYPE (uptr->flags); /* get drive type */ +uint32 dtype = GET_DTYPE (uptr->flags); /* get drive type */ -if (((uptr->flags & UNIT_ATT) == 0) || /* not attached? */ +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 */ + 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 */ +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; } @@ -475,12 +507,12 @@ return FALSE; 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 */ +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) @@ -488,21 +520,22 @@ 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_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 */ +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; } @@ -514,16 +547,18 @@ 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? */ +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 ((uptr->flags & UNIT_AUTO) == 0) return SCPE_OK; /* autosize? */ 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; } } + uptr->flags = (uptr->flags & ~UNIT_DTYPE) | (i << UNIT_V_DTYPE); + uptr->capac = drv_tab[i].size; + return SCPE_OK; + } + } return SCPE_OK; } @@ -533,8 +568,8 @@ t_stat dp_detach (UNIT *uptr) { uint32 u = uptr - dp_dev.units; -if (!(uptr->flags & UNIT_ATT)) return SCPE_OK; /* attached? */ -if (dpd_arm[u]) SET_INT (v_DPC + u + 1); /* if arm, intr */ +if (!(uptr->flags & UNIT_ATT)) return SCPE_OK; /* attached? */ +if (dpd_arm[u]) SET_INT (v_DPC + u + 1); /* if arm, intr */ return detach_unit (uptr); } @@ -553,12 +588,13 @@ 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 */ +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 index 3c06a519..f99f2a4c 100644 --- a/Interdata/id_fd.c +++ b/Interdata/id_fd.c @@ -1,6 +1,6 @@ /* id_fd.c: Interdata floppy disk simulator - Copyright (c) 2001-2004, Robert M Supnik + Copyright (c) 2001-2005, 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"), @@ -19,11 +19,11 @@ 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 + 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 + 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. @@ -36,97 +36,98 @@ #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 */ +#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 */ +#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 */ +#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 # */ +#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 */ - +#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 */ +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 }; + 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); @@ -138,62 +139,66 @@ 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 + 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) } }; + { 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 } }; + { 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 } }; + { 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 }; - + "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) @@ -201,76 +206,91 @@ 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 */ +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; } +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) @@ -278,102 +298,108 @@ t_stat fd_svc (UNIT *uptr) uint32 i, u, tk, sc, crc, fnc, da; uint8 *fbuf = uptr->filebuf; -u = uptr - fd_dev.units; /* get unit number */ -fnc = GET_FNC (uptr->FNC); /* get function */ -switch (fnc) { /* case on function */ +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_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_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] = fbuf[da + i]; - if (fbuf[FD_SIZE + uptr->LRN - 1]) { /* deleted? set err */ - fd_sta = fd_sta | STA_DEL; - 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_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] = fbuf[da + i]; + if (fbuf[FD_SIZE + uptr->LRN - 1]) { /* deleted? set err */ + fd_sta = fd_sta | STA_DEL; + 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 */ - fbuf[da + i] = fdxb[i]; /* then dir */ - fbuf[FD_SIZE + uptr->LRN - 1] = ((fnc == FNC_DEL)? 1: 0); - 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_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 */ + fbuf[da + i] = fdxb[i]; /* then dir */ + fbuf[FD_SIZE + uptr->LRN - 1] = ((fnc == FNC_DEL)? 1: 0); + 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_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_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; } + 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 */ +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 */ +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 */ +if (diff < 0) diff = -diff; /* ABS */ +if (diff < 10) diff = 10; /* MIN 10 */ +sim_activate (uptr, diff * fd_stime); /* schedule */ return; } @@ -381,9 +407,9 @@ return; 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_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; } @@ -394,15 +420,18 @@ 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; } +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; } @@ -413,10 +442,11 @@ 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; } + wrk = crc ^ dat; + crc = (crc << 1) & DMASK16; + if (wrk & SIGN16) crc = ((crc ^ 0x1020) + 1) & DMASK16; + dat = (dat << 1) & DMASK16; + } return crc; } @@ -427,53 +457,52 @@ t_stat fd_clr (DEVICE *dptr) int32 i, j; UNIT *uptr; -fd_sta = STA_IDL; /* idle */ -fd_cmd = 0; /* clear state */ +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; } +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 */ +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)) +#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 -}; + 0xD5, 0x00, 0x00, 0xCF, /* ST: AL CF */ + 0x43, 0x00, 0x00, 0x80 /* BR 80 */ + }; 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 */ +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 index 2aa7b28c..1c33ca99 100644 --- a/Interdata/id_fp.c +++ b/Interdata/id_fp.c @@ -1,6 +1,6 @@ /* id_fp.c: Interdata floating point instructions - Copyright (c) 2000-2004, Robert M. Supnik + Copyright (c) 2000-2005, 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"), @@ -19,8 +19,8 @@ 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 + 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: @@ -32,9 +32,9 @@ | 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 + 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. @@ -52,61 +52,65 @@ 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 */ +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_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 +#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_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_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))) +#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_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_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 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) +#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]; @@ -120,15 +124,15 @@ 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 */ +ReadFP2 (&fop2, op, r2, ea); /* get op, normalize */ +return StoreFPR (&fop2, op, r1, 0); /* store, chk unflo */ } /* Floating point compare */ @@ -137,105 +141,120 @@ 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)); +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 */ +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? */ +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; } + 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) + 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 */ +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? */ +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; } + 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 ^ 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 */ +uint32 f_flt (uint32 op, uint32 r1, uint32 r2) /* 16b */ { -struct ufp res = { 0, 0x44, 0, 0 }; /* +, 16**4 */ +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 */ +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 */ +uint32 f_flt32 (uint32 op, uint32 r1, uint32 r2) /* 32b */ { -struct ufp res = { 0, 0x48, 0, 0 }; /* +, 16**8 */ +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 */ +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) @@ -243,37 +262,44 @@ 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 */ +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 @@ -293,35 +319,39 @@ 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 */ +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 */ @@ -332,35 +362,39 @@ 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 */ +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 */ @@ -369,17 +403,21 @@ 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 */ +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; } @@ -389,22 +427,28 @@ 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 */ +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; } @@ -412,12 +456,14 @@ return; 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 */ +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; } @@ -427,29 +473,39 @@ 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); } +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; } @@ -459,13 +515,18 @@ 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); } +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 index 7bd72143..0beeca46 100644 --- a/Interdata/id_idc.c +++ b/Interdata/id_idc.c @@ -1,6 +1,6 @@ /* id_idc.c: Interdata MSM/IDC disk controller simulator - Copyright (c) 2001-2004, Robert M. Supnik + Copyright (c) 2001-2005, 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"), @@ -19,14 +19,14 @@ 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 + 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 + 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 + 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 @@ -34,112 +34,112 @@ #include "id_defs.h" -#define IDC_NUMBY 256 /* bytes/sector */ -#define IDC_NUMSC 64 /* sectors/track */ +#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 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 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 */ +#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) +#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 */ +#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_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 */ +#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 */ +#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 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 - */ +#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 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)) - + IDC_NUMSC)+(sc)) + /* The MSM (IDC) controller supports (two) six different disk drive types: - type #sectors/ #surfaces/ #cylinders/ - surface cylinder drive + 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 + 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 @@ -147,72 +147,73 @@ 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_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_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_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_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_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) +#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 */ -}; + 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 } }; - + { 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 */ +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); @@ -229,112 +230,116 @@ 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 + 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) } }; + { 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 } }; + { 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 } }; + { 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 }; - + "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) @@ -342,44 +347,53 @@ 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; } +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) @@ -387,42 +401,49 @@ 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; } +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 @@ -434,128 +455,146 @@ return 0; 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 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 */ +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 */ + } -case CMC_RCHK: /* read check */ - idc_dter (uptr, 1); /* check xfr err */ - break; +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 */ + 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_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_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; + 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_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_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; + case CMC_STST: case CMC_LAMP: /* tests */ + break; #endif default: - idc_sta = idc_sta | STC_DTE; - break; } + idc_sta = idc_sta | STC_DTE; + break; + } -idc_done (0); /* done */ +idc_done (0); /* done */ return SCPE_OK; } - + /* Read data sector */ t_stat idc_rds (UNIT *uptr) @@ -563,12 +602,13 @@ 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 */ +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; } @@ -577,13 +617,14 @@ return SCPE_OK; t_bool idc_wds (UNIT *uptr) { for ( ; idc_bptr < IDC_NUMBY; idc_bptr++) - idcxb[idc_bptr] = idc_db; /* fill with last */ + 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; } +if (ferror (uptr->fileref)) { /* error? */ + perror ("IDC I/O error"); + clearerr (uptr->fileref); + idc_done (STC_DTE); + return SCPE_IOERR; + } return FALSE; } @@ -593,30 +634,35 @@ t_bool idc_dter (UNIT *uptr, uint32 first) { uint32 cy; uint32 hd, sc, sa; -uint32 dtype = GET_DTYPE (uptr->flags); /* get drive type */ +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_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 */ + 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; } @@ -625,14 +671,14 @@ return FALSE; 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 */ +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) @@ -640,24 +686,25 @@ 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_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 */ +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 */ +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; } @@ -669,16 +716,18 @@ 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? */ +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 ((uptr->flags & UNIT_AUTO) == 0) return SCPE_OK; /* autosize? */ 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; } } + 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; } diff --git a/Interdata/id_io.c b/Interdata/id_io.c index 2c58f51d..af721e6a 100644 --- a/Interdata/id_io.c +++ b/Interdata/id_io.c @@ -1,6 +1,6 @@ /* id_io.c: Interdata CPU-independent I/O routines - Copyright (c) 2001-2004, Robert M. Supnik + Copyright (c) 2001-2005, 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"), @@ -19,47 +19,47 @@ 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 + 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 + 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 + 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. + 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. + 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_req[level] Indexed by interrupt level, device interrupt flags. - int_enb[level] Indexed by interrupt level, device interrupt enable 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. + 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 */ +#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); @@ -68,29 +68,29 @@ 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_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 + 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 }; @@ -98,115 +98,133 @@ 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 } }; + { 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 } }; + { 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 }; - + "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) + - 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)) +#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; } +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) @@ -229,10 +247,10 @@ return; 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 */ +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 */ @@ -242,15 +260,16 @@ 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 */ +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; } @@ -261,15 +280,16 @@ 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 */ +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; } @@ -278,11 +298,12 @@ return inc; void sch_stop (uint32 ch) { if (ch < sch_max) { - SET_INT (v_SCH + ch); /* interrupt */ - sch_cmd[ch] &= ~(SCHC_GO | SCHC_RD); } /* clear GO */ + SET_INT (v_SCH + ch); /* interrupt */ + sch_cmd[ch] &= ~(SCHC_GO | SCHC_RD); /* clear GO */ + } return; } - + /* Reset */ void sch_reset_ch (uint32 rst_lim) @@ -291,18 +312,20 @@ 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; } } + 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 */ +sch_reset_ch (0); /* reset all chan */ return SCPE_OK; } @@ -316,20 +339,23 @@ 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 */ +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; } @@ -339,12 +365,14 @@ 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]); } +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; } @@ -358,7 +386,7 @@ for (i = 0; i < sch_max; i++) sch_tplte[i] = i; sch_tplte[sch_max] = TPL_END; return; } - + /* Evaluate interrupt */ void int_eval (void) @@ -366,10 +394,12 @@ 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; } +for (i = 0; i < INTSZ; i++) { + if (int_req[i] & int_enb[i]) { + qevent = qevent | EV_INT; + return; + } + } qevent = qevent & ~EV_INT; return; } @@ -381,13 +411,17 @@ 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; } +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; } @@ -395,18 +429,21 @@ return 0; 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; } +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; } @@ -442,7 +479,7 @@ 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) @@ -458,9 +495,9 @@ 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 */ +newch = get_uint (cptr, 16, sch_max - 1, &r); /* get new */ if (r != SCPE_OK) return r; -dibp->sch = newch; /* store */ +dibp->sch = newch; /* store */ return SCPE_OK; } @@ -495,10 +532,10 @@ 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 */ +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 */ +if (newdev == 0) return SCPE_ARG; /* must be > 0 */ +dibp->dno = newdev; /* store */ return SCPE_OK; } @@ -530,38 +567,40 @@ 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; } + 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 */ +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 index 6364b9dc..9a658ca0 100644 --- a/Interdata/id_lp.c +++ b/Interdata/id_lp.c @@ -1,6 +1,6 @@ /* id_lp.c: Interdata line printer - Copyright (c) 2001-2004, Robert M. Supnik + Copyright (c) 2001-2005, 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"), @@ -19,13 +19,13 @@ 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 + 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 + lpt M46-206 line printer - 25-Apr-03 RMS Revised for extended file support + 25-Apr-03 RMS Revised for extended file support */ #include "id_defs.h" @@ -33,35 +33,35 @@ /* 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 */ +#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 */ +#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 */ +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]; @@ -73,12 +73,12 @@ 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 + 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 }; @@ -86,61 +86,70 @@ 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 } }; + { 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 } }; + { 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 }; - + "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; } +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; } @@ -151,37 +160,41 @@ 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; } +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) @@ -189,17 +202,19 @@ t_stat lpt_bufout (UNIT *uptr) int32 i; t_stat r = SCPE_OK; -if (lpt_bptr == 0) return SCPE_OK; /* any char in buf? */ +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 */ + 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; @@ -209,16 +224,19 @@ 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 */ +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) @@ -226,25 +244,27 @@ 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; } +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 */ +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 */ +CLR_INT (v_LPT); /* clearr int */ +CLR_ENB (v_LPT); /* disable int */ +lpt_arm = 0; /* disarm int */ return SCPE_OK; } @@ -252,7 +272,7 @@ return SCPE_OK; t_stat lpt_attach (UNIT *uptr, char *cptr) { -lpt_vfup = 0; /* top of form */ +lpt_vfup = 0; /* top of form */ return attach_unit (uptr, cptr); } @@ -267,21 +287,25 @@ 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; } } +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; diff --git a/Interdata/id_mt.c b/Interdata/id_mt.c index 79e3beb9..9bd8935f 100644 --- a/Interdata/id_mt.c +++ b/Interdata/id_mt.c @@ -19,29 +19,29 @@ 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 + 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 + mt M46-494 dual density 9-track magtape controller - 18-Mar-05 RMS Added attached test to detach routine - 07-Dec-04 RMS Added read-only file support - 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 + 18-Mar-05 RMS Added attached test to detach routine + 07-Dec-04 RMS Added read-only file support + 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 + 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. @@ -51,53 +51,54 @@ #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 */ +#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 */ +#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) - +#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 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 }; + 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); @@ -107,62 +108,66 @@ 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 + 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_ROABLE + UNIT_DISABLE, 0) }, - { UDATA (&mt_svc, UNIT_ATTABLE + UNIT_ROABLE + UNIT_DISABLE, 0) }, - { UDATA (&mt_svc, UNIT_ATTABLE + UNIT_ROABLE + UNIT_DISABLE, 0) }, - { UDATA (&mt_svc, UNIT_ATTABLE + UNIT_ROABLE + UNIT_DISABLE, 0) } }; + { UDATA (&mt_svc, UNIT_ATTABLE + UNIT_ROABLE + UNIT_DISABLE, 0) }, + { UDATA (&mt_svc, UNIT_ATTABLE + UNIT_ROABLE + UNIT_DISABLE, 0) }, + { UDATA (&mt_svc, UNIT_ATTABLE + UNIT_ROABLE + UNIT_DISABLE, 0) }, + { UDATA (&mt_svc, UNIT_ATTABLE + UNIT_ROABLE + 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 } }; + { 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 } }; + { 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 }; - + "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) @@ -171,59 +176,70 @@ 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; } +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 @@ -246,129 +262,137 @@ 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->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_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 */ +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; + } -switch (uptr->UCMD) { /* case on function */ +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 + 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; - For read, busy = 1 => buffer empty +/* 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 + record, or the maximum size of the transfer buffer For write, data transfers continue until a write is attempted - and the buffer is empty + 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 */ - } + 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 */ + 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; } + 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 */ + 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 */ -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_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_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_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 */ + 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 */ +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) @@ -376,33 +400,41 @@ 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 */ + + 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) @@ -410,18 +442,19 @@ 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 */ +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; } @@ -456,15 +489,13 @@ return SCPE_OK; /* Bootstrap routine */ -#define BOOT_START 0x50 -#define BOOT_LEN (sizeof (boot_rom) / sizeof (uint8)) +#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 -}; + 0xD5, 0x00, 0x00, 0xCF, /* ST: AL CF */ + 0x43, 0x00, 0x00, 0x80 /* BR 80 */ + }; t_stat mt_boot (int32 unitno, DEVICE *dptr) { @@ -473,13 +504,13 @@ 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 */ +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 index 87cf25f1..739c1769 100644 --- a/Interdata/id_pas.c +++ b/Interdata/id_pas.c @@ -1,6 +1,6 @@ /* id_pas.c: Interdata programmable async line adapter simulator - Copyright (c) 2001-2004, Robert M Supnik + Copyright (c) 2001-2005, 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"), @@ -19,14 +19,16 @@ 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 + 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) + pas Programmable asynchronous line adapter(s) - 05-Jan-04 RMS Revised for tmxr library changes - 09-May-03 RMS Added network device flag + 29-Jun-05 RMS Added SET PASLn DISCONNECT + 21-Jun-05 RMS Fixed bug in SHOW CONN/STATS + 05-Jan-04 RMS Revised for tmxr library changes + 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 @@ -41,68 +43,68 @@ #include "sim_tmxr.h" #include -#define PAS_LINES 32 +#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 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 +#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) +#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_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 */ +#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 */ +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 }; /* mux descriptor */ -#define PAS_ENAB pas_desc.lines +TMLN pas_ldsc[PAS_LINES] = { 0 }; /* line descriptors */ +TMXR pas_desc = { 8, 0, 0, pas_ldsc }; /* mux descriptor */ +#define PAS_ENAB pas_desc.lines uint32 pas (uint32 dev, uint32 op, uint32 dat); void pas_ini (t_bool dtpl); @@ -116,13 +118,13 @@ 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 + 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 }; @@ -132,105 +134,114 @@ 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 } }; + { 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 } }; + { 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 }; + "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 + 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 } }; + { 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 }, - { MTAB_XTD|MTAB_VUN|MTAB_NC, 0, "LOG", "LOG", - &tmxr_set_log, &tmxr_show_log, &pas_desc }, - { MTAB_XTD|MTAB_VUN|MTAB_NC, 0, NULL, "NOLOG", - &tmxr_set_nolog, NULL, &pas_desc }, - { 0 } }; + { 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, 0, NULL, "DISCONNECT", + &tmxr_dscln, NULL, &pas_desc }, + { MTAB_XTD|MTAB_VUN|MTAB_NC, 0, "LOG", "LOG", + &tmxr_set_log, &tmxr_show_log, &pas_desc }, + { MTAB_XTD|MTAB_VUN|MTAB_NC, 0, NULL, "NOLOG", + &tmxr_set_nolog, NULL, &pas_desc }, + { 0 } + }; REG pasl_reg[] = { - { URDATA (TIME, pasl_unit[0].wait, 16, 24, 0, - PAS_LINES, REG_NZ + PV_LEFT) }, - { NULL } }; + { 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 }; - + "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) @@ -239,50 +250,62 @@ 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_linemsg (&pas_ldsc[ln], "\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; } +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_linemsg (&pas_ldsc[ln], "\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 @@ -293,48 +316,53 @@ 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 */ +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; } @@ -343,25 +371,29 @@ return SCPE_OK; t_stat paso_svc (UNIT *uptr) { int32 c; -uint32 ln = uptr - pasl_unit; /* line # */ +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 */ +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; } @@ -369,66 +401,77 @@ 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 }; + 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; + } -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 */ +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_reset_ln (i); return SCPE_OK; } @@ -439,10 +482,10 @@ 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 */ +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 */ +sim_activate (uptr, 100); /* quick poll */ return SCPE_OK; } @@ -453,9 +496,9 @@ 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 */ +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; } @@ -475,14 +518,17 @@ return SCPE_OK; t_stat pas_show (FILE *st, UNIT *uptr, int32 val, void *desc) { -int32 i; +int32 i, t; -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); } } +for (i = t = 0; i < PAS_LINES; i++) t = t + (pas_ldsc[i].conn != 0); +if (t) { + 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; } @@ -499,20 +545,24 @@ 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_linemsg (&pas_ldsc[i], "\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); } - } + 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_linemsg (&pas_ldsc[i], "\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; } @@ -521,17 +571,17 @@ return SCPE_OK; void pas_reset_ln (int32 i) { -CLR_INT (v_PAS + i + i); /* clear int */ +CLR_INT (v_PAS + i + i); /* clear int */ CLR_ENB (v_PAS + i + i); -CLR_INT (v_PASX + i + i); /* disable int */ +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_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; +if (pas_ldsc[i].conn == 0) /* clear carrier */ + pas_sta[i] = pas_sta[i] | STA_CROF; sim_cancel (&pasl_unit[i]); return; } @@ -543,9 +593,10 @@ 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] = 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 index 0339ac30..0a7da165 100644 --- a/Interdata/id_pt.c +++ b/Interdata/id_pt.c @@ -1,6 +1,6 @@ /* id_pt.c: Interdata paper tape reader - Copyright (c) 2000-2004, Robert M. Supnik + Copyright (c) 2000-2005, 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"), @@ -19,14 +19,14 @@ 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 + 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 + 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) + 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" @@ -34,25 +34,25 @@ /* Device definitions */ -#define PTR 0 /* unit subscripts */ -#define PTP 1 +#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 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 */ +#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 */ +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); @@ -60,270 +60,278 @@ 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 + 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 } }; + { 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 } }; + { 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 } }; + { 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 }; - + "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; } +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 */ +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 */ +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[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 */ +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)) +#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 -}; + 0xD5, 0x00, 0x00, 0xCF, /* ST AL CF */ + 0x43, 0x00, 0x00, 0x80 /* BR 80 */ + }; 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 -}; + 0xC8, 0x20, 0x00, 0x80, /* ST LHI 2,80 */ + 0xC8, 0x30, 0x00, 0x01, /* LHI 3,1 */ + 0xC8, 0x40, 0x00, 0xCF, /* LHI 4,CF */ + 0xD3, 0xA0, 0x00, 0x78, /* LB A,78 */ + 0xDE, 0xA0, 0x00, 0x79, /* OC A,79 */ + 0x9D, 0xAE, /* LP SSR A,E */ + 0x42, 0xF0, 0x00, 0x52, /* BTC F,LP */ + 0x9B, 0xAE, /* RDR A,E */ + 0x08, 0xEE, /* LHR E,E */ + 0x43, 0x30, 0x00, 0x52, /* BZ LP */ + 0x43, 0x00, 0x00, 0x6C, /* BR STO */ + 0x9D, 0xAE, /* LP1 SSR A,E */ + 0x42, 0xF0, 0x00, 0x64, /* BTC F,LP1 */ + 0x9B, 0xAE, /* RDR A,E */ + 0xD2, 0xE2, 0x00, 0x00, /* STO STB E,0(2) */ + 0xC1, 0x20, 0x00, 0x64, /* BXLE 2,LP1 */ + 0x43, 0x00, 0x00, 0x80 /* BR 80 */ + }; 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 */ +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 +#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 */ -}; + 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) { @@ -344,7 +352,7 @@ 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); + 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); diff --git a/Interdata/id_tt.c b/Interdata/id_tt.c index 0a284813..8dbda083 100644 --- a/Interdata/id_tt.c +++ b/Interdata/id_tt.c @@ -1,6 +1,6 @@ /* id_tt.c: Interdata teletype - Copyright (c) 2000-2004, Robert M. Supnik + Copyright (c) 2000-2005, 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"), @@ -19,45 +19,45 @@ 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 + 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 + tt console - 29-Dec-03 RMS Added support for console backpressure - 25-Apr-03 RMS Revised for extended file support - 11-Jan-03 RMS Added TTP support - 22-Dec-02 RMS Added break support + 29-Dec-03 RMS Added support for console backpressure + 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) +#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 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 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 */ +#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_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); @@ -66,96 +66,109 @@ 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 + 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 } -}; + { 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 } }; + { 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 } }; + { 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 }; - + "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; } +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; } @@ -165,26 +178,30 @@ 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 */ +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; } +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; } @@ -193,19 +210,23 @@ t_stat tto_svc (UNIT *uptr) int32 ch; t_stat r; -if (uptr->flags & UNIT_KSR) { /* KSR mode? */ - ch = uptr->buf & 0x7F; /* mask to 7b */ - if (islower (ch)) ch = toupper (ch); } /* cvt to UC */ +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))) { /* supr NULL, DEL */ - if ((r = sim_putchar_s (ch)) != SCPE_OK) { /* output; error? */ - sim_activate (uptr, uptr->wait); /* try again */ - return ((r == SCPE_STALL)? SCPE_OK: r); } } -if (!tt_rd) { /* write mode? */ - tt_sta = tt_sta & ~STA_BSY; /* clear busy */ - if (tt_arm) SET_INT (v_TT); } /* if armed, intr */ -uptr->pos = uptr->pos + 1; /* incr count */ +if ((uptr->flags & UNIT_8B) || /* KSR or 7b? */ + ((ch != 0) && (ch != 0x7F))) { /* supr NULL, DEL */ + if ((r = sim_putchar_s (ch)) != SCPE_OK) { /* output; error? */ + sim_activate (uptr, uptr->wait); /* try again */ + return ((r == SCPE_STALL)? SCPE_OK: r); + } + } +if (!tt_rd) { /* write mode? */ + tt_sta = tt_sta & ~STA_BSY; /* clear busy */ + if (tt_arm) SET_INT (v_TT); /* if armed, intr */ + } +uptr->pos = uptr->pos + 1; /* incr count */ return SCPE_OK; } @@ -213,15 +234,15 @@ return SCPE_OK; 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 */ +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; } @@ -240,11 +261,12 @@ 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 */ +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; } diff --git a/Interdata/id_ttp.c b/Interdata/id_ttp.c index befc71fe..6b9c9d3c 100644 --- a/Interdata/id_ttp.c +++ b/Interdata/id_ttp.c @@ -1,6 +1,6 @@ /* id_ttp.c: Interdata PASLA console interface - Copyright (c) 2000-2004, Robert M. Supnik + Copyright (c) 2000-2005, 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"), @@ -19,49 +19,49 @@ 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 + 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) + ttp console (on PAS) - 29-Dec-03 RMS Added support for console backpressure - 25-Apr-03 RMS Revised for extended file support + 29-Dec-03 RMS Added support for console backpressure + 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 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 +#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) +#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 */ +#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 */ +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); @@ -73,56 +73,58 @@ 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 } -}; + { 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 } }; + { 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 } }; + { 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 }; + "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) @@ -130,64 +132,77 @@ 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; } +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? */ +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; } } +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; } @@ -196,19 +211,23 @@ t_stat ttpo_svc (UNIT *uptr) int32 c; t_stat r; -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))){ /* supr NULL, DEL */ - if ((r = sim_putchar_s (c)) != SCPE_OK) { /* output; error? */ - sim_activate (uptr, uptr->wait); /* try again */ - return ((r == SCPE_STALL)? SCPE_OK: r); } } -ttp_sta = ttp_sta & ~STA_BSY; /* not busy */ -if (ttp_tarm) SET_INT (v_TTP + 1); /* set intr */ -uptr->pos = uptr->pos + 1; /* incr count */ +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))){ /* supr NULL, DEL */ + if ((r = sim_putchar_s (c)) != SCPE_OK) { /* output; error? */ + sim_activate (uptr, uptr->wait); /* try again */ + return ((r == SCPE_STALL)? SCPE_OK: r); + } + } +ttp_sta = ttp_sta & ~STA_BSY; /* not busy */ +if (ttp_tarm) SET_INT (v_TTP + 1); /* set intr */ +uptr->pos = uptr->pos + 1; /* incr count */ return SCPE_OK; } @@ -216,16 +235,14 @@ return SCPE_OK; 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_INT (v_TTP); /* clear int */ CLR_ENB (v_TTP); -CLR_INT (v_TTP + 1); /* disable int */ +CLR_INT (v_TTP + 1); /* disable int */ CLR_ENB (v_TTP + 1); -ttp_karm = ttp_tarm = 0; /* disarm int */ +ttp_karm = ttp_tarm = 0; /* disarm int */ ttp_cmd = 0; ttp_sta = 0; ttp_kchp = 0; @@ -247,8 +264,8 @@ 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 */ +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; } diff --git a/Interdata/id_uvc.c b/Interdata/id_uvc.c index de84c613..5fce2d1e 100644 --- a/Interdata/id_uvc.c +++ b/Interdata/id_uvc.c @@ -1,6 +1,6 @@ /* id_uvc.c: Interdata universal clock - Copyright (c) 2001-2004, Robert M. Supnik + Copyright (c) 2001-2005, 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"), @@ -19,15 +19,16 @@ 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 + 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 + 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 + 23-Jul-05 RMS Fixed {} error in OC + 01-Mar-03 RMS Added SET/SHOW LFC FREQ support + Changed precision clock algorithm for V7 UNIX */ #include "id_defs.h" @@ -35,35 +36,36 @@ /* Device definitions */ -#define UNIT_V_DIAG (UNIT_V_UF + 0) /* diag mode */ -#define UNIT_DIAG (1 << UNIT_V_DIAG) +#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 +#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 */ +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 }; +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); @@ -72,8 +74,8 @@ 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 */ +int32 lfc_tps = 120; /* ticks per */ +uint32 lfc_arm = 0; /* int arm */ DEVICE lfc_dev; uint32 lfc (uint32 dev, uint32 op, uint32 dat); @@ -81,12 +83,12 @@ 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 + 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 }; @@ -94,41 +96,44 @@ 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 } }; + { 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 } }; + { 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 }; + "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 + 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 }; @@ -136,76 +141,89 @@ 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 } }; + { 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 } }; + { 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 }; - + "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 */ +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; } @@ -215,16 +233,17 @@ 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; } +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; } @@ -239,34 +258,38 @@ 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 */ +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; } +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; } @@ -274,34 +297,38 @@ return pic_cic; t_stat pic_reset (DEVICE *dptr) { -sim_cancel (&pic_unit); /* cancel unit */ +sim_cancel (&pic_unit); /* cancel unit */ pic_ric = pic_cic = 0; pic_db = 0; -pic_ovf = 0; /* clear state */ +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 */ +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; } +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; } @@ -311,11 +338,12 @@ 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 */ +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; } @@ -323,10 +351,10 @@ return SCPE_OK; 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 */ +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; } diff --git a/LGP/lgp_cpu.c b/LGP/lgp_cpu.c index d16fd003..5b4a47cb 100644 --- a/LGP/lgp_cpu.c +++ b/LGP/lgp_cpu.c @@ -19,19 +19,20 @@ 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 + 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 LGP-30 [LGP-21] CPU + cpu LGP-30 [LGP-21] CPU - 04-Jan-05 RMS Modified VM pointer setup + 04-Sep-05 RMS Fixed missing returns (found by Peter Schorn) + 04-Jan-05 RMS Modified VM pointer setup The system state for the LGP-30 [LGP-21] is: - A<0:31> accumulator - C<0:11> counter (PC) - OVF overflow flag [LGP-21 only] + A<0:31> accumulator + C<0:11> counter (PC) + OVF overflow flag [LGP-21 only] The LGP-30 [LGP-21] has just one instruction format: @@ -43,58 +44,57 @@ LGP-30 instructions: - <0,12:15> operation + <0,12:15> operation - 0 stop - 1 A <- M[ea] - 2 M[ea] <- A - 3 M[ea] <- C + 1 - 4 input - 5 A <- A / M[ea] - 6 A <- A * M[ea], low result - 7 A <- A * M[ea], high result - 8 output - 9 A <- A & M[ea] - A C <- ea - B C <- ea if A < 0 - -B C <- ea if (A < 0) || T-switch set - C M[ea] <- A - D M[ea] <- A, A <- 0 - E A <- A + M[ea] - F A <- A - M[ea] + 0 stop + 1 A <- M[ea] + 2 M[ea] <- A + 3 M[ea] <- C + 1 + 4 input + 5 A <- A / M[ea] + 6 A <- A * M[ea], low result + 7 A <- A * M[ea], high result + 8 output + 9 A <- A & M[ea] + A C <- ea + B C <- ea if A < 0 + -B C <- ea if (A < 0) || T-switch set + C M[ea] <- A + D M[ea] <- A, A <- 0 + E A <- A + M[ea] + F A <- A - M[ea] LGP-21 instructions: - <0,12:15> operation + <0,12:15> operation - 0 stop; sense and skip - -0 stop; sense overflow and skip - 1 A <- M[ea] - 2 M[ea] <- A - 3 M[ea] <- C + 1 - 4 6b input - -4 4b input - 5 A <- A / M[ea] - 6 A <- A * M[ea], low result - 7 A <- A * M[ea], high result - 8 6b output - -8 4b output - 9 A <- A & M[ea] - A C <- ea - B C <- ea if A < 0 - -B C <- ea if (A < 0) || T-switch set - C M[ea] <- A - D M[ea] <- A, A <- 0 - E A <- A + M[ea] - F A <- A - M[ea] + 0 stop; sense and skip + -0 stop; sense overflow and skip + 1 A <- M[ea] + 2 M[ea] <- A + 3 M[ea] <- C + 1 + 4 6b input + -4 4b input + 5 A <- A / M[ea] + 6 A <- A * M[ea], low result + 7 A <- A * M[ea], high result + 8 6b output + -8 4b output + 9 A <- A & M[ea] + A C <- ea + B C <- ea if A < 0 + -B C <- ea if (A < 0) || T-switch set + C M[ea] <- A + D M[ea] <- A, A <- 0 + E A <- A + M[ea] + F A <- A - M[ea] The LGP-30 [LGP-21] has 4096 32b words of memory. The low order bit is always read and stored as 0. The LGP-30 uses a drum for memory, with 64 tracks of 64 words. The LGP-21 uses a disk for memory, with 32 tracks of 128 words. -*/ - -/* This routine is the instruction decode routine for the LGP-30 + + This routine is the instruction decode routine for the LGP-30 [LGP-21]. 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. @@ -103,10 +103,10 @@ 1. Reasons to stop. The simulator can be stopped by: - STOP instruction - breakpoint encountered - overflow [LGP-30] - I/O error in I/O simulator + STOP instruction + breakpoint encountered + overflow [LGP-30] + I/O error in I/O simulator 2. Interrupts. There are no interrupts. @@ -115,40 +115,40 @@ 4. Adding I/O devices. The LGP-30 could not support additional I/O devices. The LGP-21 could but none are known. */ - + #include "lgp_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 - 1) & AMASK; -#define M16 0xFFFF -#define M32 0xFFFFFFFF -#define NEG(x) ((~(x) + 1) & DMASK) -#define ABS(x) (((x) & SIGN)? NEG (x): (x)) +#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 - 1) & AMASK; +#define M16 0xFFFF +#define M32 0xFFFFFFFF +#define NEG(x) ((~(x) + 1) & DMASK) +#define ABS(x) (((x) & SIGN)? NEG (x): (x)) -uint32 M[MEMSIZE] = { 0 }; /* memory */ -uint32 PC = 0; /* counter */ -uint32 A = 0; /* accumulator */ -uint32 IR = 0; /* instr register */ -uint32 OVF = 0; /* overflow indicator */ -uint32 t_switch = 0; /* transfer switch */ -uint32 bp32 = 0; /* BP32 switch */ -uint32 bp16 = 0; /* BP16 switch */ -uint32 bp8 = 0; /* BP8 switch */ -uint32 bp4 = 0; /* BP4 switch */ -uint32 inp_strt = 0; /* input started */ -uint32 inp_done = 0; /* input done */ -uint32 out_strt = 0; /* output started */ -uint32 out_done = 0; /* output done */ -uint32 lgp21_sov = 0; /* LGP-21 sense pending */ +uint32 M[MEMSIZE] = { 0 }; /* memory */ +uint32 PC = 0; /* counter */ +uint32 A = 0; /* accumulator */ +uint32 IR = 0; /* instr register */ +uint32 OVF = 0; /* overflow indicator */ +uint32 t_switch = 0; /* transfer switch */ +uint32 bp32 = 0; /* BP32 switch */ +uint32 bp16 = 0; /* BP16 switch */ +uint32 bp8 = 0; /* BP8 switch */ +uint32 bp4 = 0; /* BP4 switch */ +uint32 inp_strt = 0; /* input started */ +uint32 inp_done = 0; /* input done */ +uint32 out_strt = 0; /* output started */ +uint32 out_done = 0; /* output done */ +uint32 lgp21_sov = 0; /* LGP-21 sense pending */ int32 delay = 0; -int16 pcq[PCQ_SIZE] = { 0 }; /* PC queue */ -int32 pcq_p = 0; /* PC queue ptr */ -REG *pcq_r = NULL; /* PC queue reg ptr */ +int16 pcq[PCQ_SIZE] = { 0 }; /* PC queue */ +int32 pcq_p = 0; /* PC queue ptr */ +REG *pcq_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 */ +extern int32 sim_brk_types, sim_brk_dflt, sim_brk_summ; /* breakpoint info */ extern int32 sim_step; t_stat cpu_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw); @@ -170,94 +170,103 @@ uint32 shift_in (uint32 a, uint32 dat, uint32 sh4); extern t_stat op_p (uint32 dev, uint32 ch); extern t_stat op_i (uint32 dev, uint32 ch, uint32 sh4); extern void lgp_vm_init (void); - + /* CPU data structures - cpu_dev CPU device descriptor - cpu_unit CPU unit descriptor - cpu_reg CPU register list - cpu_mod CPU modifiers list + 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_IN4B+UNIT_TTSS_D, MEMSIZE) }; REG cpu_reg[] = { - { DRDATA (C, PC, 12), REG_VMAD }, - { HRDATA (A, A, 32), REG_VMIO }, - { HRDATA (IR, IR, 32), REG_VMIO }, - { FLDATA (OVF, OVF, 0) }, - { FLDATA (TSW, t_switch, 0) }, - { FLDATA (BP32, bp32, 0) }, - { FLDATA (BP16, bp16, 0) }, - { FLDATA (BP8, bp8, 0) }, - { FLDATA (BP4, bp4, 0) }, - { FLDATA (INPST, inp_strt, 0) }, - { FLDATA (INPDN, inp_done, 0) }, - { FLDATA (OUTST, out_strt, 0) }, - { FLDATA (OUTDN, out_done, 0) }, - { DRDATA (DELAY, delay, 7) }, - { BRDATA (CQ, pcq, 16, 12, PCQ_SIZE), REG_RO + REG_CIRC }, - { HRDATA (CQP, pcq_p, 6), REG_HRO }, - { HRDATA (WRU, sim_int_char, 8) }, - { NULL } }; + { DRDATA (C, PC, 12), REG_VMAD }, + { HRDATA (A, A, 32), REG_VMIO }, + { HRDATA (IR, IR, 32), REG_VMIO }, + { FLDATA (OVF, OVF, 0) }, + { FLDATA (TSW, t_switch, 0) }, + { FLDATA (BP32, bp32, 0) }, + { FLDATA (BP16, bp16, 0) }, + { FLDATA (BP8, bp8, 0) }, + { FLDATA (BP4, bp4, 0) }, + { FLDATA (INPST, inp_strt, 0) }, + { FLDATA (INPDN, inp_done, 0) }, + { FLDATA (OUTST, out_strt, 0) }, + { FLDATA (OUTDN, out_done, 0) }, + { DRDATA (DELAY, delay, 7) }, + { BRDATA (CQ, pcq, 16, 12, PCQ_SIZE), REG_RO + REG_CIRC }, + { HRDATA (CQP, pcq_p, 6), REG_HRO }, + { HRDATA (WRU, sim_int_char, 8) }, + { NULL } + }; MTAB cpu_mod[] = { - { UNIT_LGP21, UNIT_LGP21, "LGP-21", "LGP21", &cpu_set_model, &cpu_show_model }, - { UNIT_LGP21, 0, "LGP-30", "LGP30", &cpu_set_model, &cpu_show_model }, - { UNIT_TTSS_D, UNIT_TTSS_D, 0, "TRACK" }, - { UNIT_TTSS_D, 0, 0, "NORMAL" }, - { UNIT_LGPH_D, UNIT_LGPH_D, 0, "LGPHEX" }, - { UNIT_LGPH_D, 0, 0, "STANDARDHEX" }, - { UNIT_MANI, UNIT_MANI, NULL, "MANUAL" }, - { UNIT_MANI, 0, NULL, "TAPE" }, - { UNIT_IN4B, UNIT_IN4B, NULL, "4B", &cpu_set_30opt }, - { UNIT_IN4B, 0, NULL, "6B", &cpu_set_30opt }, - { MTAB_XTD|MTAB_VDV, 0, NULL, "INPUT", &cpu_set_30opt_i }, - { MTAB_XTD|MTAB_VDV, 0, NULL, "OUTPUT", &cpu_set_30opt_o }, - { MTAB_XTD|MTAB_VDV, 0, NULL, "EXECUTE", &cpu_set_exec }, - { MTAB_XTD|MTAB_VDV, 0, NULL, "FILL", &cpu_set_fill }, - { 0 } }; + { UNIT_LGP21, UNIT_LGP21, "LGP-21", "LGP21", &cpu_set_model, &cpu_show_model }, + { UNIT_LGP21, 0, "LGP-30", "LGP30", &cpu_set_model, &cpu_show_model }, + { UNIT_TTSS_D, UNIT_TTSS_D, 0, "TRACK" }, + { UNIT_TTSS_D, 0, 0, "NORMAL" }, + { UNIT_LGPH_D, UNIT_LGPH_D, 0, "LGPHEX" }, + { UNIT_LGPH_D, 0, 0, "STANDARDHEX" }, + { UNIT_MANI, UNIT_MANI, NULL, "MANUAL" }, + { UNIT_MANI, 0, NULL, "TAPE" }, + { UNIT_IN4B, UNIT_IN4B, NULL, "4B", &cpu_set_30opt }, + { UNIT_IN4B, 0, NULL, "6B", &cpu_set_30opt }, + { MTAB_XTD|MTAB_VDV, 0, NULL, "INPUT", &cpu_set_30opt_i }, + { MTAB_XTD|MTAB_VDV, 0, NULL, "OUTPUT", &cpu_set_30opt_o }, + { MTAB_XTD|MTAB_VDV, 0, NULL, "EXECUTE", &cpu_set_exec }, + { MTAB_XTD|MTAB_VDV, 0, NULL, "FILL", &cpu_set_fill }, + { 0 } + }; DEVICE cpu_dev = { - "CPU", &cpu_unit, cpu_reg, cpu_mod, - 1, 10, 12, 1, 16, 32, - &cpu_ex, &cpu_dep, &cpu_reset, - NULL, NULL, NULL }; - + "CPU", &cpu_unit, cpu_reg, cpu_mod, + 1, 10, 12, 1, 16, 32, + &cpu_ex, &cpu_dep, &cpu_reset, + NULL, NULL, NULL + }; + /* Timing tables */ /* Optimization minima and maxima - Z B Y R I D N M P E U T H C A S */ + Z B Y R I D N M P E U T H C A S */ static const int32 min_30[16] = { - 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 + }; static const int32 max_30[16] = { - 7, 7, 7, 7, 7, 5, 8, 6, 7, 7, 0, 0, 7, 7, 7, 7 }; + 7, 7, 7, 7, 7, 5, 8, 6, 7, 7, 0, 0, 7, 7, 7, 7 + }; static const int32 min_21[16] = { - 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 + }; static const int32 max_21[16] = { - 0, 16, 16, 16, 0, 58, 81, 79, 0, 16, 0, 0, 16, 16, 16, 16 }; + 0, 16, 16, 16, 0, 58, 81, 79, 0, 16, 0, 0, 16, 16, 16, 16 + }; -static const uint32 log_to_phys_30[NSC_30] = { /* drum interlace chart */ - 0, 57, 50, 43, 36, 29, 22, 15, 8 , - 1, 58, 51, 44, 37, 30, 23, 16, 9 , - 2, 59, 52, 45, 38, 31, 24, 17, 10, - 3, 60, 53, 46, 39, 32, 25, 18, 11, - 4, 61, 54, 47, 40, 33, 26, 19, 12, - 5, 62, 55, 48, 41, 32, 27, 20, 13, - 6, 63, 56, 49, 42, 33, 28, 21, 14, - 7 }; +static const uint32 log_to_phys_30[NSC_30] = { /* drum interlace chart */ + 0, 57, 50, 43, 36, 29, 22, 15, 8 , + 1, 58, 51, 44, 37, 30, 23, 16, 9 , + 2, 59, 52, 45, 38, 31, 24, 17, 10, + 3, 60, 53, 46, 39, 32, 25, 18, 11, + 4, 61, 54, 47, 40, 33, 26, 19, 12, + 5, 62, 55, 48, 41, 32, 27, 20, 13, + 6, 63, 56, 49, 42, 33, 28, 21, 14, + 7 + }; + +static const uint32 log_to_phys_21[NSC_21] = { /* disk interlace chart */ + 0, 64, 57, 121, 50, 114, 43, 107, 36, 100, 29, 93, 22, 86, 15, 79, 8, 72, + 1, 65, 58, 122, 51, 115, 44, 108, 37, 101, 30, 94, 23, 87, 16, 80, 9, 73, + 2, 66, 59, 123, 52, 116, 45, 109, 38, 102, 31, 95, 24, 88, 17, 81, 10, 74, + 3, 67, 60, 124, 53, 117, 46, 110, 39, 103, 32, 96, 25, 89, 18, 82, 11, 75, + 4, 68, 61, 125, 54, 118, 47, 111, 40, 104, 33, 97, 26, 90, 19, 83, 12, 76, + 5, 69, 62, 126, 55, 119, 48, 112, 41, 105, 34, 98, 27, 91, 20, 84, 12, 77, + 6, 70, 63, 127, 56, 120, 49, 113, 42, 106, 35, 99, 28, 92, 21, 85, 13, 78, + 7, 71 + }; -static const uint32 log_to_phys_21[NSC_21] = { /* disk interlace chart */ - 0, 64, 57, 121, 50, 114, 43, 107, 36, 100, 29, 93, 22, 86, 15, 79, 8, 72, - 1, 65, 58, 122, 51, 115, 44, 108, 37, 101, 30, 94, 23, 87, 16, 80, 9, 73, - 2, 66, 59, 123, 52, 116, 45, 109, 38, 102, 31, 95, 24, 88, 17, 81, 10, 74, - 3, 67, 60, 124, 53, 117, 46, 110, 39, 103, 32, 96, 25, 89, 18, 82, 11, 75, - 4, 68, 61, 125, 54, 118, 47, 111, 40, 104, 33, 97, 26, 90, 19, 83, 12, 76, - 5, 69, 62, 126, 55, 119, 48, 112, 41, 105, 34, 98, 27, 91, 20, 84, 12, 77, - 6, 70, 63, 127, 56, 120, 49, 113, 42, 106, 35, 99, 28, 92, 21, 85, 13, 78, - 7, 71 }; - t_stat sim_instr (void) { t_stat r = 0; @@ -265,46 +274,53 @@ uint32 oPC; /* Restore register state */ -PC = PC & AMASK; /* mask PC */ -sim_cancel_step (); /* defang SCP step */ -if (lgp21_sov) { /* stop sense pending? */ - lgp21_sov = 0; - if (!OVF) PC = (PC + 1) & AMASK; /* ovf off? skip */ - else OVF = 0; } /* on? reset */ +PC = PC & AMASK; /* mask PC */ +sim_cancel_step (); /* defang SCP step */ +if (lgp21_sov) { /* stop sense pending? */ + lgp21_sov = 0; + if (!OVF) PC = (PC + 1) & AMASK; /* ovf off? skip */ + else OVF = 0; /* on? reset */ + } /* Main instruction fetch/decode loop */ -do { if (sim_interval <= 0) { /* check clock queue */ - if (r = sim_process_event ()) break; } +do { + if (sim_interval <= 0) { /* check clock queue */ + if (r = sim_process_event ()) break; + } - if (delay > 0) { /* delay to next instr */ - delay = delay - 1; /* count down delay */ - sim_interval = sim_interval - 1; - continue; } /* skip execution */ + if (delay > 0) { /* delay to next instr */ + delay = delay - 1; /* count down delay */ + sim_interval = sim_interval - 1; + continue; /* skip execution */ + } - if (sim_brk_summ && /* breakpoint? */ - sim_brk_test (PC, SWMASK ('E'))) { - r = STOP_IBKPT; /* stop simulation */ - break; } + if (sim_brk_summ && /* breakpoint? */ + sim_brk_test (PC, SWMASK ('E'))) { + r = STOP_IBKPT; /* stop simulation */ + break; + } - IR = Read (oPC = PC); /* get instruction */ - PC = (PC + 1) & AMASK; /* increment PC */ - sim_interval = sim_interval - 1; + IR = Read (oPC = PC); /* get instruction */ + PC = (PC + 1) & AMASK; /* increment PC */ + sim_interval = sim_interval - 1; - if (r = cpu_one_inst (oPC, IR)) { /* one instr; error? */ - if (r == STOP_STALL) { /* stall? */ - PC = oPC; /* back up PC */ - delay = r = 0; } /* no delay */ - else break; } + if (r = cpu_one_inst (oPC, IR)) { /* one instr; error? */ + if (r == STOP_STALL) { /* stall? */ + PC = oPC; /* back up PC */ + delay = r = 0; /* no delay */ + } + else break; + } - if (sim_step && (--sim_step <= 0)) /* do step count */ - r = SCPE_STOP; + if (sim_step && (--sim_step <= 0)) /* do step count */ + r = SCPE_STOP; - } while (r == 0); /* loop until halted */ -pcq_r->qptr = pcq_p; /* update pc q ptr */ + } while (r == 0); /* loop until halted */ +pcq_r->qptr = pcq_p; /* update pc q ptr */ return r; } - + /* Execute one instruction */ t_stat cpu_one_inst (uint32 opc, uint32 ir) @@ -313,160 +329,171 @@ uint32 ea, op, dat, res, dev, sh4, ch; t_bool ovf_this_cycle = FALSE; t_stat reason = 0; -op = I_GETOP (ir); /* opcode */ -ea = I_GETEA (ir); /* address */ -switch (op) { /* case on opcode */ +op = I_GETOP (ir); /* opcode */ +ea = I_GETEA (ir); /* address */ +switch (op) { /* case on opcode */ /* Loads, stores, transfers instructions */ -case OP_B: /* bring */ - A = Read (ea); /* A <- M[ea] */ - delay = I_delay (opc, ea, op); - break; + case OP_B: /* bring */ + A = Read (ea); /* A <- M[ea] */ + delay = I_delay (opc, ea, op); + break; -case OP_H: /* hold */ - Write (ea, A); /* M[ea] <- A */ - delay = I_delay (opc, ea, op); - break; + case OP_H: /* hold */ + Write (ea, A); /* M[ea] <- A */ + delay = I_delay (opc, ea, op); + break; -case OP_C: /* clear */ - Write (ea, A); /* M[ea] <- A */ - A = 0; /* A <- 0 */ - delay = I_delay (opc, ea, op); - break; + case OP_C: /* clear */ + Write (ea, A); /* M[ea] <- A */ + A = 0; /* A <- 0 */ + delay = I_delay (opc, ea, op); + break; -case OP_Y: /* store address */ - dat = Read (ea); /* get operand */ - dat = (dat & ~I_EA) | (A & I_EA); /* merge address */ - Write (ea, dat); - delay = I_delay (opc, ea, op); - break; + case OP_Y: /* store address */ + dat = Read (ea); /* get operand */ + dat = (dat & ~I_EA) | (A & I_EA); /* merge address */ + Write (ea, dat); + delay = I_delay (opc, ea, op); + break; -case OP_R: /* return address */ - dat = Read (ea); /* get operand */ - dat = (dat & ~I_EA) | (((PC + 1) & AMASK) << I_V_EA); - Write (ea, dat); - delay = I_delay (opc, ea, op); - break; + case OP_R: /* return address */ + dat = Read (ea); /* get operand */ + dat = (dat & ~I_EA) | (((PC + 1) & AMASK) << I_V_EA); + Write (ea, dat); + delay = I_delay (opc, ea, op); + break; -case OP_U: /* uncond transfer */ - PCQ_ENTRY; - PC = ea; /* transfer */ - delay = I_delay (opc, ea, op); - break; + case OP_U: /* uncond transfer */ + PCQ_ENTRY; + PC = ea; /* transfer */ + delay = I_delay (opc, ea, op); + break; + + case OP_T: /* conditional transfer */ + if ((A & SIGN) || /* A < 0 or */ + ((ir & SIGN) && t_switch)) { /* -T and Tswitch set? */ + PCQ_ENTRY; + PC = ea; /* transfer */ + } + delay = I_delay (opc, ea, op); + break; -case OP_T: /* conditional transfer */ - if ((A & SIGN) || /* A < 0 or */ - ((ir & SIGN) && t_switch)) { /* -T and Tswitch set? */ - PCQ_ENTRY; - PC = ea; } /* transfer */ - delay = I_delay (opc, ea, op); - break; - /* Arithmetic and logical instructions */ -case OP_A: /* add */ - dat = Read (ea); /* get operand */ - res = (A + dat) & DMASK; /* add */ - if ((~A ^ dat) & (dat ^ res) & SIGN) /* calc overflow */ - ovf_this_cycle = TRUE; - A = res; /* save result */ - delay = I_delay (opc, ea, op); - break; + case OP_A: /* add */ + dat = Read (ea); /* get operand */ + res = (A + dat) & DMASK; /* add */ + if ((~A ^ dat) & (dat ^ res) & SIGN) /* calc overflow */ + ovf_this_cycle = TRUE; + A = res; /* save result */ + delay = I_delay (opc, ea, op); + break; -case OP_S: /* sub */ - dat = Read (ea); /* get operand */ - res = (A - dat) & DMASK; /* subtract */ - if ((A ^ dat) & (~dat ^ res) & SIGN) /* calc overflow */ - ovf_this_cycle = TRUE; - A = res; - delay = I_delay (opc, ea, op); - break; + case OP_S: /* sub */ + dat = Read (ea); /* get operand */ + res = (A - dat) & DMASK; /* subtract */ + if ((A ^ dat) & (~dat ^ res) & SIGN) /* calc overflow */ + ovf_this_cycle = TRUE; + A = res; + delay = I_delay (opc, ea, op); + break; -case OP_M: /* multiply high */ - dat = Read (ea); /* get operand */ - A = (Mul64 (A, dat, NULL) << 1) & DMASK; /* multiply */ - delay = I_delay (opc, ea, op); - break; + case OP_M: /* multiply high */ + dat = Read (ea); /* get operand */ + A = (Mul64 (A, dat, NULL) << 1) & DMASK; /* multiply */ + delay = I_delay (opc, ea, op); + break; -case OP_N: /* multiply low */ - dat = Read (ea); /* get operand */ - Mul64 (A, dat, &res); /* multiply */ - A = res; /* keep low result */ - delay = I_delay (opc, ea, op); /* total delay */ - break; + case OP_N: /* multiply low */ + dat = Read (ea); /* get operand */ + Mul64 (A, dat, &res); /* multiply */ + A = res; /* keep low result */ + delay = I_delay (opc, ea, op); /* total delay */ + break; -case OP_D: /* divide */ - dat = Read (ea); /* get operand */ - if (Div32 (A, dat, &A)) ovf_this_cycle = TRUE; /* divide; overflow? */ - delay = I_delay (opc, ea, op); - break; + case OP_D: /* divide */ + dat = Read (ea); /* get operand */ + if (Div32 (A, dat, &A)) ovf_this_cycle = TRUE; /* divide; overflow? */ + delay = I_delay (opc, ea, op); + break; + + case OP_E: /* extract */ + dat = Read (ea); /* get operand */ + A = A & dat; /* and */ + delay = I_delay (opc, ea, op); + break; -case OP_E: /* extract */ - dat = Read (ea); /* get operand */ - A = A & dat; /* and */ - delay = I_delay (opc, ea, op); - break; - /* IO instructions */ -case OP_P: /* output */ - if (Q_LGP21) { /* LGP-21 */ - ch = A >> 26; /* char, 6b */ - if (ir & SIGN) ch = (ch & 0x3C) | 2; /* 4b? convert */ - dev = I_GETTK (ir); } /* device select */ - else { /* LGP-30 */ - ch = I_GETTK (ir); /* char, always 6b */ - dev = Q_OUTPT? DEV_PT: DEV_TT; } /* device select */ - reason = op_p (dev & DEV_MASK, ch); /* output */ - delay = I_delay (sim_grtime (), ea, op); /* next instruction */ - break; + case OP_P: /* output */ + if (Q_LGP21) { /* LGP-21 */ + ch = A >> 26; /* char, 6b */ + if (ir & SIGN) ch = (ch & 0x3C) | 2; /* 4b? convert */ + dev = I_GETTK (ir); /* device select */ + } + else { /* LGP-30 */ + ch = I_GETTK (ir); /* char, always 6b */ + dev = Q_OUTPT? DEV_PT: DEV_TT; /* device select */ + } + reason = op_p (dev & DEV_MASK, ch); /* output */ + delay = I_delay (sim_grtime (), ea, op); /* next instruction */ + break; -case OP_I: /* input */ - if (Q_LGP21) { /* LGP-21 */ - ch = 0; /* initial shift */ - sh4 = ir & SIGN; /* 4b/6b select */ - dev = I_GETTK (ir); } /* device select */ - else { /* LGP-30 */ - ch = I_GETTK (ir); /* initial shift */ - sh4 = Q_IN4B; /* 4b/6b select */ - dev = Q_INPT? DEV_PT: DEV_TT; } /* device select */ - if (dev == DEV_SHIFT) /* shift? */ - A = shift_in (A, 0, sh4); /* shift 4/6b */ - else reason = op_i (dev & DEV_MASK, ch, sh4); /* input */ - delay = I_delay (sim_grtime (), ea, op); /* next instruction */ - break; + case OP_I: /* input */ + if (Q_LGP21) { /* LGP-21 */ + ch = 0; /* initial shift */ + sh4 = ir & SIGN; /* 4b/6b select */ + dev = I_GETTK (ir); /* device select */ + } + else { /* LGP-30 */ + ch = I_GETTK (ir); /* initial shift */ + sh4 = Q_IN4B; /* 4b/6b select */ + dev = Q_INPT? DEV_PT: DEV_TT; /* device select */ + } + if (dev == DEV_SHIFT) /* shift? */ + A = shift_in (A, 0, sh4); /* shift 4/6b */ + else reason = op_i (dev & DEV_MASK, ch, sh4); /* input */ + delay = I_delay (sim_grtime (), ea, op); /* next instruction */ + break; -case OP_Z: - if (Q_LGP21) { /* LGP-21 */ - if (ea & 0xF80) { /* no stop? */ - if (((ea & 0x800) && !bp32) || /* skip if any */ - ((ea & 0x400) && !bp16) || /* selected switch */ - ((ea & 0x200) && !bp8) || /* is off */ - ((ea & 0x100) && !bp4) || /* or if */ - ((ir & SIGN) && !OVF)) /* ovf sel and off */ - PC = (PC + 1) & AMASK; - if (ir & SIGN) OVF = 0; } /* -Z? clr overflow */ - else { /* stop */ - lgp21_sov = (ir & SIGN)? 1: 0; /* pending sense? */ - reason = STOP_STOP; } } /* stop */ - else { /* LGP-30 */ - if (out_done) out_done = 0; /* P complete? */ - else if (((ea & 0x800) && bp32) || /* bpt switch set? */ - ((ea & 0x400) && bp16) || - ((ea & 0x200) && bp8) || - ((ea & 0x100) && bp4)) ; /* don't stop or stall */ - else if (out_strt) reason = STOP_STALL; /* P pending? stall */ - else reason = STOP_STOP; } /* no, stop */ - delay = I_delay (sim_grtime (), ea, op); /* next instruction */ - break; } /* end switch */ + case OP_Z: + if (Q_LGP21) { /* LGP-21 */ + if (ea & 0xF80) { /* no stop? */ + if (((ea & 0x800) && !bp32) || /* skip if any */ + ((ea & 0x400) && !bp16) || /* selected switch */ + ((ea & 0x200) && !bp8) || /* is off */ + ((ea & 0x100) && !bp4) || /* or if */ + ((ir & SIGN) && !OVF)) /* ovf sel and off */ + PC = (PC + 1) & AMASK; + if (ir & SIGN) OVF = 0; /* -Z? clr overflow */ + } + else { /* stop */ + lgp21_sov = (ir & SIGN)? 1: 0; /* pending sense? */ + reason = STOP_STOP; /* stop */ + } + } + else { /* LGP-30 */ + if (out_done) out_done = 0; /* P complete? */ + else if (((ea & 0x800) && bp32) || /* bpt switch set? */ + ((ea & 0x400) && bp16) || + ((ea & 0x200) && bp8) || + ((ea & 0x100) && bp4)) ; /* don't stop or stall */ + else if (out_strt) reason = STOP_STALL; /* P pending? stall */ + else reason = STOP_STOP; /* no, stop */ + } + delay = I_delay (sim_grtime (), ea, op); /* next instruction */ + break; /* end switch */ + } if (ovf_this_cycle) { - if (Q_LGP21) OVF = 1; /* LGP-21? set OVF */ - else reason = STOP_OVF; } /* LGP-30? stop */ + if (Q_LGP21) OVF = 1; /* LGP-21? set OVF */ + else reason = STOP_OVF; /* LGP-30? stop */ + } return reason; } - + /* Support routines */ uint32 Read (uint32 ea) @@ -495,28 +522,30 @@ uint32 Mul64 (uint32 a, uint32 b, uint32 *low) uint32 sgn = a ^ b; uint32 ah, bh, al, bl, rhi, rlo, rmid1, rmid2; -if ((a == 0) || (b == 0)) { /* zero argument? */ - if (low) *low = 0; - return 0; } +if ((a == 0) || (b == 0)) { /* zero argument? */ + if (low) *low = 0; + return 0; + } a = ABS (a); b = ABS (b); -ah = (a >> 16) & M16; /* split operands */ -bh = (b >> 16) & M16; /* into 16b chunks */ +ah = (a >> 16) & M16; /* split operands */ +bh = (b >> 16) & M16; /* into 16b chunks */ al = a & M16; bl = b & M16; -rhi = ah * bh; /* high result */ +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 */ -if (sgn & SIGN) { /* result negative? */ - rmid2 = NEG (rmid2); /* negate */ - rhi = (~rhi + (rmid2 == 0)) & M32; } -if (low) *low = rmid2; /* low result */ +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 */ +if (sgn & SIGN) { /* result negative? */ + rmid2 = NEG (rmid2); /* negate */ + rhi = (~rhi + (rmid2 == 0)) & M32; + } +if (low) *low = rmid2; /* low result */ return rhi & M32; } @@ -530,16 +559,18 @@ uint32 i, quo; dvd = ABS (dvd); dvr = ABS (dvr); if (dvd >= dvr) return TRUE; -for (i = quo = 0; i < 31; i++) { /* 31 iterations */ - quo = quo << 1; /* shift quotient */ - dvd = dvd << 1; /* shift dividend */ - if (dvd >= dvr) { /* step work? */ - dvd = (dvd - dvr) & M32; /* subtract dvr */ - quo = quo + 1; } } -quo = (quo + 1) & MMASK; /* round low bit */ -if (sgn & SIGN) quo = NEG (quo); /* result -? */ -if (q) *q = quo; /* return quo */ -return FALSE; /* no overflow */ +for (i = quo = 0; i < 31; i++) { /* 31 iterations */ + quo = quo << 1; /* shift quotient */ + dvd = dvd << 1; /* shift dividend */ + if (dvd >= dvr) { /* step work? */ + dvd = (dvd - dvr) & M32; /* subtract dvr */ + quo = quo + 1; + } + } +quo = (quo + 1) & MMASK; /* round low bit */ +if (sgn & SIGN) quo = NEG (quo); /* result -? */ +if (q) *q = quo; /* return quo */ +return FALSE; /* no overflow */ } /* Rotational delay */ @@ -550,26 +581,30 @@ uint32 tmin = Q_LGP21? min_21[op]: min_30[op]; uint32 tmax = Q_LGP21? max_21[op]: max_30[op]; uint32 nsc, curp, newp, oprp, pcdelta, opdelta; -if (Q_LGP21) { /* LGP21 */ - nsc = NSC_21; /* full rotation delay */ - curp = log_to_phys_21[opc & SCMASK_21]; /* current phys pos */ - newp = log_to_phys_21[PC & SCMASK_21]; /* new PC phys pos */ - oprp = log_to_phys_21[ea & SCMASK_21]; /* ea phys pos */ - pcdelta = (newp - curp + NSC_21) & SCMASK_21; - opdelta = (oprp - curp + NSC_21) & SCMASK_21; } -else { nsc = NSC_30; - curp = log_to_phys_30[opc & SCMASK_30]; - newp = log_to_phys_30[PC & SCMASK_30]; - oprp = log_to_phys_30[ea & SCMASK_30]; - pcdelta = (newp - curp + NSC_30) & SCMASK_30; - opdelta = (oprp - curp + NSC_30) & SCMASK_30; } -if (tmax == 0) { /* skip ea calc? */ - if (pcdelta >= tmin) return pcdelta - 1; /* new PC >= min? */ - return pcdelta + nsc - 1; } +if (Q_LGP21) { /* LGP21 */ + nsc = NSC_21; /* full rotation delay */ + curp = log_to_phys_21[opc & SCMASK_21]; /* current phys pos */ + newp = log_to_phys_21[PC & SCMASK_21]; /* new PC phys pos */ + oprp = log_to_phys_21[ea & SCMASK_21]; /* ea phys pos */ + pcdelta = (newp - curp + NSC_21) & SCMASK_21; + opdelta = (oprp - curp + NSC_21) & SCMASK_21; + } +else { + nsc = NSC_30; + curp = log_to_phys_30[opc & SCMASK_30]; + newp = log_to_phys_30[PC & SCMASK_30]; + oprp = log_to_phys_30[ea & SCMASK_30]; + pcdelta = (newp - curp + NSC_30) & SCMASK_30; + opdelta = (oprp - curp + NSC_30) & SCMASK_30; + } +if (tmax == 0) { /* skip ea calc? */ + if (pcdelta >= tmin) return pcdelta - 1; /* new PC >= min? */ + return pcdelta + nsc - 1; + } if ((opdelta >= tmin) && (opdelta <= tmax)) return pcdelta - 1; return pcdelta + nsc - 1; } - + /* Reset routine */ t_stat cpu_reset (DEVICE *dptr) @@ -636,9 +671,10 @@ if (uptr->flags & UNIT_TTSS_D) fputs (", track/sector", st); if (uptr->flags & UNIT_LGPH_D) fputs (", LGP hex", st); fputs (Q_MANI? ", manual": ", tape", st); if (!Q_LGP21) { - fputs (Q_IN4B? ", 4b": ", 6b", st); - fputs (Q_INPT? ", in=PTR": ", in=TTI", st); - fputs (Q_OUTPT? ", out=PTP": ", out=TTO", st); } + fputs (Q_IN4B? ", 4b": ", 6b", st); + fputs (Q_INPT? ", in=PTR": ", in=TTI", st); + fputs (Q_OUTPT? ", out=PTP": ", out=TTO", st); + } return SCPE_OK; } @@ -668,12 +704,14 @@ uint32 inst; t_stat r; if (cptr) { - inst = get_uint (cptr, 16, DMASK, &r); - if (r != SCPE_OK) r; } + inst = get_uint (cptr, 16, DMASK, &r); + if (r != SCPE_OK) return r; + } else inst = IR; while ((r = cpu_one_inst (PC, inst)) == STOP_STALL) { - sim_interval = 0; - if (r = sim_process_event ()) return r; } + sim_interval = 0; + if (r = sim_process_event ()) return r; + } return r; } @@ -685,9 +723,10 @@ uint32 inst; t_stat r; if (cptr) { - inst = get_uint (cptr, 16, DMASK, &r); - if (r != SCPE_OK) r; - IR = inst; } + inst = get_uint (cptr, 16, DMASK, &r); + if (r != SCPE_OK) return r; + IR = inst; + } else IR = A; return SCPE_OK; } diff --git a/LGP/lgp_defs.h b/LGP/lgp_defs.h index c40c3f78..d8b2d677 100644 --- a/LGP/lgp_defs.h +++ b/LGP/lgp_defs.h @@ -1,6 +1,6 @@ /* lgp_defs.h: LGP simulator definitions - Copyright (c) 2004, Robert M. Supnik + Copyright (c) 2004-2005, 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"), @@ -19,112 +19,113 @@ 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 + Except as contained in this notice, the name of Robert M Supnik shall not be 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 _LGP_DEFS_H_ -#define _LGP_DEFS_H_ 0 +#define _LGP_DEFS_H_ 0 -#include "sim_defs.h" /* simulator defns */ +#include "sim_defs.h" /* simulator defns */ /* Simulator stop codes */ -#define STOP_STOP 1 /* STOP */ -#define STOP_IBKPT 2 /* breakpoint */ -#define STOP_OVF 3 /* overflow */ -#define STOP_NXDEV 4 /* non-existent device */ -#define STOP_STALL 5 /* IO stall */ +#define STOP_STOP 1 /* STOP */ +#define STOP_IBKPT 2 /* breakpoint */ +#define STOP_OVF 3 /* overflow */ +#define STOP_NXDEV 4 /* non-existent device */ +#define STOP_STALL 5 /* IO stall */ /* Memory */ -#define MEMSIZE 4096 /* memory size */ -#define AMASK 0xFFF /* addr mask */ -#define NTK_30 64 -#define NSC_30 64 -#define SCMASK_30 0x03F /* sector mask */ -#define NTK_21 32 -#define NSC_21 128 -#define SCMASK_21 0x07F -#define RPM 4000 /* rev/minutes */ -#define WPS ((NSC_30 * RPM) / 60) /* words/second */ +#define MEMSIZE 4096 /* memory size */ +#define AMASK 0xFFF /* addr mask */ +#define NTK_30 64 +#define NSC_30 64 +#define SCMASK_30 0x03F /* sector mask */ +#define NTK_21 32 +#define NSC_21 128 +#define SCMASK_21 0x07F +#define RPM 4000 /* rev/minutes */ +#define WPS ((NSC_30 * RPM) / 60) /* words/second */ /* Architectural constants */ -#define SIGN 0x80000000 /* sign */ -#define DMASK 0xFFFFFFFF /* data mask */ -#define MMASK 0xFFFFFFFE /* memory mask */ +#define SIGN 0x80000000 /* sign */ +#define DMASK 0xFFFFFFFF /* data mask */ +#define MMASK 0xFFFFFFFE /* memory mask */ /* Instruction format */ -#define I_M_OP 0xF /* opcode */ -#define I_V_OP 16 -#define I_OP (I_M_OP << I_V_OP) -#define I_GETOP(x) (((x) >> I_V_OP) & I_M_OP) -#define I_M_EA AMASK /* address */ -#define I_V_EA 2 -#define I_EA (I_M_EA << I_V_EA) -#define I_GETEA(x) (((x) >> I_V_EA) & I_M_EA) -#define I_M_TK 0x3F /* LGP-30 char */ -#define I_V_TK 8 /* LGP-21 device */ -#define I_GETTK(x) (((x) >> I_V_TK) & I_M_TK) +#define I_M_OP 0xF /* opcode */ +#define I_V_OP 16 +#define I_OP (I_M_OP << I_V_OP) +#define I_GETOP(x) (((x) >> I_V_OP) & I_M_OP) +#define I_M_EA AMASK /* address */ +#define I_V_EA 2 +#define I_EA (I_M_EA << I_V_EA) +#define I_GETEA(x) (((x) >> I_V_EA) & I_M_EA) +#define I_M_TK 0x3F /* LGP-30 char */ +#define I_V_TK 8 /* LGP-21 device */ +#define I_GETTK(x) (((x) >> I_V_TK) & I_M_TK) /* Unit flags */ -#define UNIT_V_LGP21 (UNIT_V_UF + 0) -#define UNIT_V_MANI (UNIT_V_UF + 1) -#define UNIT_V_INPT (UNIT_V_UF + 2) -#define UNIT_V_OUTPT (UNIT_V_UF + 3) -#define UNIT_V_IN4B (UNIT_V_UF + 4) -#define UNIT_V_TTSS_D (UNIT_V_UF + 5) -#define UNIT_V_LGPH_D (UNIT_V_UF + 6) -#define UNIT_V_FLEX_D (UNIT_V_UF + 7) /* Flex default */ -#define UNIT_V_FLEX (UNIT_V_UF + 8) /* Flex format */ -#define UNIT_V_NOCS (UNIT_V_UF + 9) /* ignore cond stop */ -#define UNIT_LGP21 (1u << UNIT_V_LGP21) -#define UNIT_MANI (1u << UNIT_V_MANI) -#define UNIT_INPT (1u << UNIT_V_INPT) -#define UNIT_OUTPT (1u << UNIT_V_OUTPT) -#define UNIT_IN4B (1u << UNIT_V_IN4B) -#define UNIT_TTSS_D (1u << UNIT_V_TTSS_D) -#define UNIT_LGPH_D (1u << UNIT_V_LGPH_D) -#define UNIT_FLEX_D (1u << UNIT_V_FLEX_D) -#define UNIT_FLEX (1u << UNIT_V_FLEX) -#define UNIT_NOCS (1u << UNIT_V_NOCS) -#define Q_LGP21 (cpu_unit.flags & UNIT_LGP21) -#define Q_MANI (cpu_unit.flags & UNIT_MANI) -#define Q_INPT (cpu_unit.flags & UNIT_INPT) -#define Q_OUTPT (cpu_unit.flags & UNIT_OUTPT) -#define Q_IN4B (cpu_unit.flags & UNIT_IN4B) +#define UNIT_V_LGP21 (UNIT_V_UF + 0) +#define UNIT_V_MANI (UNIT_V_UF + 1) +#define UNIT_V_INPT (UNIT_V_UF + 2) +#define UNIT_V_OUTPT (UNIT_V_UF + 3) +#define UNIT_V_IN4B (UNIT_V_UF + 4) +#define UNIT_V_TTSS_D (UNIT_V_UF + 5) +#define UNIT_V_LGPH_D (UNIT_V_UF + 6) +#define UNIT_V_FLEX_D (UNIT_V_UF + 7) /* Flex default */ +#define UNIT_V_FLEX (UNIT_V_UF + 8) /* Flex format */ +#define UNIT_V_NOCS (UNIT_V_UF + 9) /* ignore cond stop */ +#define UNIT_LGP21 (1u << UNIT_V_LGP21) +#define UNIT_MANI (1u << UNIT_V_MANI) +#define UNIT_INPT (1u << UNIT_V_INPT) +#define UNIT_OUTPT (1u << UNIT_V_OUTPT) +#define UNIT_IN4B (1u << UNIT_V_IN4B) +#define UNIT_TTSS_D (1u << UNIT_V_TTSS_D) +#define UNIT_LGPH_D (1u << UNIT_V_LGPH_D) +#define UNIT_FLEX_D (1u << UNIT_V_FLEX_D) +#define UNIT_FLEX (1u << UNIT_V_FLEX) +#define UNIT_NOCS (1u << UNIT_V_NOCS) +#define Q_LGP21 (cpu_unit.flags & UNIT_LGP21) +#define Q_MANI (cpu_unit.flags & UNIT_MANI) +#define Q_INPT (cpu_unit.flags & UNIT_INPT) +#define Q_OUTPT (cpu_unit.flags & UNIT_OUTPT) +#define Q_IN4B (cpu_unit.flags & UNIT_IN4B) /* IO return */ -#define IORETURN(f,v) ((f)? (v): SCPE_OK) /* stop on error */ +#define IORETURN(f,v) ((f)? (v): SCPE_OK) /* stop on error */ /* Significant characters */ -#define FLEX_LC 0x04 -#define FLEX_UC 0x08 -#define FLEX_CR 0x10 -#define FLEX_BS 0x14 -#define FLEX_CSTOP 0x20 -#define FLEX_DEL 0x3F +#define FLEX_LC 0x04 +#define FLEX_UC 0x08 +#define FLEX_CR 0x10 +#define FLEX_BS 0x14 +#define FLEX_CSTOP 0x20 +#define FLEX_DEL 0x3F /* LGP-21 device assignments */ -#define DEV_PT 0 -#define DEV_TT 2 -#define DEV_MASK 0x1F -#define DEV_SHIFT 62 +#define DEV_PT 0 +#define DEV_TT 2 +#define DEV_MASK 0x1F +#define DEV_SHIFT 62 /* Instructions */ enum opcodes { - OP_Z, OP_B, OP_Y, OP_R, - OP_I, OP_D, OP_N, OP_M, - OP_P, OP_E, OP_U, OP_T, - OP_H, OP_C, OP_A, OP_S }; + OP_Z, OP_B, OP_Y, OP_R, + OP_I, OP_D, OP_N, OP_M, + OP_P, OP_E, OP_U, OP_T, + OP_H, OP_C, OP_A, OP_S + }; /* Prototypes */ diff --git a/LGP/lgp_doc.txt b/LGP/lgp_doc.txt index 253ada4b..c00b7fb9 100644 --- a/LGP/lgp_doc.txt +++ b/LGP/lgp_doc.txt @@ -27,8 +27,8 @@ The following copyright notice applies to both the SIMH source and binary: 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 + 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. diff --git a/LGP/lgp_stddev.c b/LGP/lgp_stddev.c index d6619ccc..080e4aca 100644 --- a/LGP/lgp_stddev.c +++ b/LGP/lgp_stddev.c @@ -1,6 +1,6 @@ /* lgp_stddev.c: LGP-30 standard devices - Copyright (c) 2004, Robert M Supnik + Copyright (c) 2004-2005, 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"), @@ -19,14 +19,14 @@ 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 + 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 typewriter input (keyboard and reader) - tto typewriter output (printer and punch) - ptr high speed reader - ptpp high speed punch + tti typewriter input (keyboard and reader) + tto typewriter output (printer and punch) + ptr high speed reader + ptpp high speed punch */ #include "lgp_defs.h" @@ -67,403 +67,457 @@ t_stat punch_feed (UNIT *uptr, int32 val, char *cptr, void *desc); t_stat send_start (UNIT *uptr, int32 val, char *cptr, void *desc); extern uint32 shift_in (uint32 a, uint32 dat, uint32 sh4); - + /* Conversion tables */ const int32 flex_to_ascii[128] = { - -1 , 'z', '0', ' ', '>', 'b', '1', '-', - '<' , 'y', '2', '+', '|', 'r', '3', ';', - '\r', 'i', '4', '/','\\', 'd', '5', '.', - '\t', 'n', '6', ',', -1 , 'm', '7', 'v', - '\'', 'p', '8', 'o', -1 , 'e', '9', 'x', - -1 , 'u', 'f', -1 , -1 , 't', 'g', -1 , - -1 , 'h', 'j', -1 , -1 , 'c', 'k', -1 , - -1 , 'a', 'q', -1 , -1 , 's', 'w', 0 , + -1 , 'z', '0', ' ', '>', 'b', '1', '-', + '<' , 'y', '2', '+', '|', 'r', '3', ';', + '\r', 'i', '4', '/','\\', 'd', '5', '.', + '\t', 'n', '6', ',', -1 , 'm', '7', 'v', + '\'', 'p', '8', 'o', -1 , 'e', '9', 'x', + -1 , 'u', 'f', -1 , -1 , 't', 'g', -1 , + -1 , 'h', 'j', -1 , -1 , 'c', 'k', -1 , + -1 , 'a', 'q', -1 , -1 , 's', 'w', 0 , - -1 , 'Z', ')', ' ', -1 , 'B', 'L', '_', - -1 , 'Y', '*', '=', '|', 'R', '"', ':', - '\r', 'I', '^', '?','\\', 'D', '%', ']', - '\t', 'N', '$', '[', -1 , 'M', '~', 'V', - '\'', 'P', '#', 'O', -1 , 'E', '(', 'X', - -1 , 'U', 'F', -1 , -1 , 'T', 'G', -1 , - -1 , 'H', 'J', -1 , -1 , 'C', 'K', -1 , - -1 , 'A', 'Q', -1 , -1 , 'S', 'W', 0 }; + -1 , 'Z', ')', ' ', -1 , 'B', 'L', '_', + -1 , 'Y', '*', '=', '|', 'R', '"', ':', + '\r', 'I', '^', '?','\\', 'D', '%', ']', + '\t', 'N', '$', '[', -1 , 'M', '~', 'V', + '\'', 'P', '#', 'O', -1 , 'E', '(', 'X', + -1 , 'U', 'F', -1 , -1 , 'T', 'G', -1 , + -1 , 'H', 'J', -1 , -1 , 'C', 'K', -1 , + -1 , 'A', 'Q', -1 , -1 , 'S', 'W', 0 + }; const int32 ascii_to_flex[128] = { - -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , - 024, 030, -1 , -1 , -1 , 020, -1 , -1 , - -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , - -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , - 003, -1 , 016, 042, 032, 026, -1 , 040, - 046, 001, 012, 013, 033, 007, 027, 023, - 002, 006, 012, 016, 022, 026, 032, 036, - 042, 046, 017, 017, 004, 013, 010, 023, - -1 , 071, 005, 065, 025, 045, 052, 056, - 061, 021, 062, 066, 006, 035, 031, 043, - 041, 072, 015, 075, 055, 051, 037, 076, - 047, 011, 001, 033, -1 , 027, 022, 007, - - 1, 071, 005, 065, 025, 045, 052, 056, - 061, 021, 062, 066, 006, 035, 031, 043, - 041, 072, 015, 075, 055, 051, 037, 076, - 047, 011, 001, -1 , 014, -1 , 036, 077 }; - + -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , + 024, 030, -1 , -1 , -1 , 020, -1 , -1 , + -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , + -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , + 003, -1 , 016, 042, 032, 026, -1 , 040, + 046, 001, 012, 013, 033, 007, 027, 023, + 002, 006, 012, 016, 022, 026, 032, 036, + 042, 046, 017, 017, 004, 013, 010, 023, + -1 , 071, 005, 065, 025, 045, 052, 056, + 061, 021, 062, 066, 006, 035, 031, 043, + 041, 072, 015, 075, 055, 051, 037, 076, + 047, 011, 001, 033, -1 , 027, 022, 007, + - 1, 071, 005, 065, 025, 045, 052, 056, + 061, 021, 062, 066, 006, 035, 031, 043, + 041, 072, 015, 075, 055, 051, 037, 076, + 047, 011, 001, -1 , 014, -1 , 036, 077 + }; + static const uint8 flex_inp_valid[64] = { - 1, 1, 1, 1, 0, 1, 1, 1, - 0, 1, 1, 1, 0, 1, 1, 1, - 0, 1, 1, 1, 0, 1, 1, 1, - 0, 1, 1, 1, 0, 1, 1, 1, - 1, 1, 1, 1, 0, 1, 1, 1, - 0, 1, 1, 1, 0, 1, 1, 1, - 0, 1, 1, 1, 0, 1, 1, 1, - 0, 1, 1, 1, 0, 1, 1, 1 }; - + 1, 1, 1, 1, 0, 1, 1, 1, + 0, 1, 1, 1, 0, 1, 1, 1, + 0, 1, 1, 1, 0, 1, 1, 1, + 0, 1, 1, 1, 0, 1, 1, 1, + 1, 1, 1, 1, 0, 1, 1, 1, + 0, 1, 1, 1, 0, 1, 1, 1, + 0, 1, 1, 1, 0, 1, 1, 1, + 0, 1, 1, 1, 0, 1, 1, 1 + }; + /* TTI data structures - tti_dev TTI device descriptor - tti_unit TTI unit descriptor - tti_mod TTI modifier list - tti_reg TTI register list + tti_dev TTI device descriptor + tti_unit TTI unit descriptor + tti_mod TTI modifier list + tti_reg TTI register list */ UNIT tti_unit[] = { - { UDATA (&tti_svc, 0, 0) }, - { UDATA (&ttr_svc, UNIT_SEQ+UNIT_ATTABLE+UNIT_ROABLE, 0) } }; + { UDATA (&tti_svc, 0, 0) }, + { UDATA (&ttr_svc, UNIT_SEQ+UNIT_ATTABLE+UNIT_ROABLE, 0) } + }; REG tti_reg[] = { - { HRDATA (BUF, tti_buf, 6) }, - { FLDATA (RDY, tti_rdy, 0) }, - { DRDATA (KPOS, tti_unit[0].pos, T_ADDR_W), PV_LEFT }, - { DRDATA (RPOS, tti_unit[1].pos, T_ADDR_W), PV_LEFT }, - { DRDATA (TIME, tt_wait, 24), REG_NZ + PV_LEFT }, - { FLDATA (STOP_IOE, ttr_stopioe, 0) }, - { NULL } }; + { HRDATA (BUF, tti_buf, 6) }, + { FLDATA (RDY, tti_rdy, 0) }, + { DRDATA (KPOS, tti_unit[0].pos, T_ADDR_W), PV_LEFT }, + { DRDATA (RPOS, tti_unit[1].pos, T_ADDR_W), PV_LEFT }, + { DRDATA (TIME, tt_wait, 24), REG_NZ + PV_LEFT }, + { FLDATA (STOP_IOE, ttr_stopioe, 0) }, + { NULL } + }; MTAB tti_mod[] = { - { UNIT_FLEX_D, UNIT_FLEX_D, NULL, "FLEX", &tap_attable }, - { UNIT_FLEX_D, 0, NULL, "ASCII", &tap_attable }, - { UNIT_ATT+UNIT_FLEX, UNIT_ATT+UNIT_FLEX, - "file is Flex", NULL }, - { UNIT_ATT+UNIT_FLEX, UNIT_ATT, - "file is ASCII", NULL }, - { UNIT_ATTABLE+UNIT_ATT+UNIT_FLEX, UNIT_ATTABLE+UNIT_FLEX, - "default is Flex", NULL }, - { UNIT_ATTABLE+UNIT_ATT+UNIT_FLEX, UNIT_ATTABLE, - "default is ASCII", NULL }, - { UNIT_ATTABLE+UNIT_NOCS, UNIT_ATTABLE+UNIT_NOCS, - "ignore conditional stop", "NOCSTOP", &tap_attable }, - { UNIT_ATTABLE+UNIT_NOCS, UNIT_ATTABLE , - NULL, "CSTOP", &tap_attable }, - { MTAB_XTD|MTAB_VDV, 0, NULL, "START", &send_start }, - { MTAB_XTD|MTAB_VDV, 1, NULL, "RSTART", &tti_rdrss }, - { MTAB_XTD|MTAB_VDV, 0, NULL, "RSTOP", &tti_rdrss }, - { 0, 0 } }; + { UNIT_FLEX_D, UNIT_FLEX_D, NULL, "FLEX", &tap_attable }, + { UNIT_FLEX_D, 0, NULL, "ASCII", &tap_attable }, + { UNIT_ATT+UNIT_FLEX, UNIT_ATT+UNIT_FLEX, + "file is Flex", NULL }, + { UNIT_ATT+UNIT_FLEX, UNIT_ATT, + "file is ASCII", NULL }, + { UNIT_ATTABLE+UNIT_ATT+UNIT_FLEX, UNIT_ATTABLE+UNIT_FLEX, + "default is Flex", NULL }, + { UNIT_ATTABLE+UNIT_ATT+UNIT_FLEX, UNIT_ATTABLE, + "default is ASCII", NULL }, + { UNIT_ATTABLE+UNIT_NOCS, UNIT_ATTABLE+UNIT_NOCS, + "ignore conditional stop", "NOCSTOP", &tap_attable }, + { UNIT_ATTABLE+UNIT_NOCS, UNIT_ATTABLE , + NULL, "CSTOP", &tap_attable }, + { MTAB_XTD|MTAB_VDV, 0, NULL, "START", &send_start }, + { MTAB_XTD|MTAB_VDV, 1, NULL, "RSTART", &tti_rdrss }, + { MTAB_XTD|MTAB_VDV, 0, NULL, "RSTOP", &tti_rdrss }, + { 0 } + }; DEVICE tti_dev = { - "TTI", tti_unit, tti_reg, tti_mod, - 2, 10, 31, 1, 16, 7, - NULL, NULL, &tti_reset, - NULL, &tap_attach, NULL }; + "TTI", tti_unit, tti_reg, tti_mod, + 2, 10, 31, 1, 16, 7, + NULL, NULL, &tti_reset, + NULL, &tap_attach, NULL + }; /* TTO data structures - tto_dev TTO device descriptor - tto_unit TTO unit descriptor - tto_mod TTO modifier list - tto_reg TTO register list + tto_dev TTO device descriptor + tto_unit TTO unit descriptor + tto_mod TTO modifier list + tto_reg TTO register list */ UNIT tto_unit[] = { - { UDATA (&tto_svc, 0, 0) }, - { UDATA (NULL, UNIT_SEQ+UNIT_ATTABLE, 0) } }; + { UDATA (&tto_svc, 0, 0) }, + { UDATA (NULL, UNIT_SEQ+UNIT_ATTABLE, 0) } + }; REG tto_reg[] = { - { HRDATA (BUF, tto_buf, 6) }, - { FLDATA (UC, tto_uc, 0) }, - { DRDATA (TPOS, tto_unit[0].pos, T_ADDR_W), PV_LEFT }, - { DRDATA (PPOS, tto_unit[1].pos, T_ADDR_W), PV_LEFT }, - { DRDATA (TIME, tt_wait, 24), PV_LEFT }, - { NULL } }; + { HRDATA (BUF, tto_buf, 6) }, + { FLDATA (UC, tto_uc, 0) }, + { DRDATA (TPOS, tto_unit[0].pos, T_ADDR_W), PV_LEFT }, + { DRDATA (PPOS, tto_unit[1].pos, T_ADDR_W), PV_LEFT }, + { DRDATA (TIME, tt_wait, 24), PV_LEFT }, + { NULL } + }; MTAB tto_mod[] = { - { UNIT_FLEX_D, UNIT_FLEX_D, NULL, "FLEX", &tap_attable }, - { UNIT_FLEX_D, 0, NULL, "ASCII", &tap_attable }, - { UNIT_ATT+UNIT_FLEX, UNIT_ATT+UNIT_FLEX, - "file is Flex", NULL }, - { UNIT_ATT+UNIT_FLEX, UNIT_ATT, - "file is ASCII", NULL }, - { UNIT_ATTABLE+UNIT_ATT+UNIT_FLEX, UNIT_ATTABLE+UNIT_FLEX, - "default is Flex", NULL }, - { UNIT_ATTABLE+UNIT_ATT+UNIT_FLEX, UNIT_ATTABLE, - "default is ASCII", NULL }, - { MTAB_XTD|MTAB_VUN, 0, NULL, "FEED", &punch_feed }, - { 0, 0 } }; + { UNIT_FLEX_D, UNIT_FLEX_D, NULL, "FLEX", &tap_attable }, + { UNIT_FLEX_D, 0, NULL, "ASCII", &tap_attable }, + { UNIT_ATT+UNIT_FLEX, UNIT_ATT+UNIT_FLEX, + "file is Flex", NULL }, + { UNIT_ATT+UNIT_FLEX, UNIT_ATT, + "file is ASCII", NULL }, + { UNIT_ATTABLE+UNIT_ATT+UNIT_FLEX, UNIT_ATTABLE+UNIT_FLEX, + "default is Flex", NULL }, + { UNIT_ATTABLE+UNIT_ATT+UNIT_FLEX, UNIT_ATTABLE, + "default is ASCII", NULL }, + { MTAB_XTD|MTAB_VUN, 0, NULL, "FEED", &punch_feed }, + { 0 } + }; DEVICE tto_dev = { - "TTO", tto_unit, tto_reg, tto_mod, - 2, 10, 31, 1, 16, 7, - NULL, NULL, &tto_reset, - NULL, &tap_attach, NULL }; - + "TTO", tto_unit, tto_reg, tto_mod, + 2, 10, 31, 1, 16, 7, + NULL, NULL, &tto_reset, + NULL, &tap_attach, NULL + }; + /* PTR data structures - ptr_dev PTR device descriptor - ptr_unit PTR unit descriptor - ptr_mod PTR modifier list - ptr_reg PTR register list + ptr_dev PTR device descriptor + ptr_unit PTR unit descriptor + ptr_mod PTR modifier list + ptr_reg PTR register list */ UNIT ptr_unit = { - UDATA (&ptr_svc, UNIT_SEQ+UNIT_ATTABLE+UNIT_ROABLE, 0), WPS / 200 }; + UDATA (&ptr_svc, UNIT_SEQ+UNIT_ATTABLE+UNIT_ROABLE, 0), WPS / 200 + }; REG ptr_reg[] = { - { HRDATA (BUF, ptr_unit.buf, 6) }, - { FLDATA (RDY, ptr_rdy, 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 } }; + { HRDATA (BUF, ptr_unit.buf, 6) }, + { FLDATA (RDY, ptr_rdy, 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[] = { - { UNIT_FLEX_D, UNIT_FLEX_D, NULL, "FLEX", &tap_attable }, - { UNIT_FLEX_D, 0, NULL, "ASCII", &tap_attable }, - { UNIT_ATT+UNIT_FLEX, UNIT_ATT+UNIT_FLEX, - "file is Flex", NULL }, - { UNIT_ATT+UNIT_FLEX, UNIT_ATT, - "file is ASCII", NULL }, - { UNIT_ATTABLE+UNIT_ATT+UNIT_FLEX, UNIT_ATTABLE+UNIT_FLEX, - "default is Flex", NULL }, - { UNIT_ATTABLE+UNIT_ATT+UNIT_FLEX, UNIT_ATTABLE, - "default is ASCII", NULL }, - { 0, 0 } }; + { UNIT_FLEX_D, UNIT_FLEX_D, NULL, "FLEX", &tap_attable }, + { UNIT_FLEX_D, 0, NULL, "ASCII", &tap_attable }, + { UNIT_ATT+UNIT_FLEX, UNIT_ATT+UNIT_FLEX, + "file is Flex", NULL }, + { UNIT_ATT+UNIT_FLEX, UNIT_ATT, + "file is ASCII", NULL }, + { UNIT_ATTABLE+UNIT_ATT+UNIT_FLEX, UNIT_ATTABLE+UNIT_FLEX, + "default is Flex", NULL }, + { UNIT_ATTABLE+UNIT_ATT+UNIT_FLEX, UNIT_ATTABLE, + "default is ASCII", NULL }, + { 0 } + }; DEVICE ptr_dev = { - "PTR", &ptr_unit, ptr_reg, ptr_mod, - 1, 10, 31, 1, 16, 7, - NULL, NULL, &ptr_reset, - NULL, &tap_attach, NULL }; + "PTR", &ptr_unit, ptr_reg, ptr_mod, + 1, 10, 31, 1, 16, 7, + NULL, NULL, &ptr_reset, + NULL, &tap_attach, NULL + }; /* PTP data structures - ptp_dev PTP device descriptor - ptp_unit PTP unit descriptor - ptp_mod PTP modifier list - ptp_reg PTP register list + ptp_dev PTP device descriptor + ptp_unit PTP unit descriptor + ptp_mod PTP modifier list + ptp_reg PTP register list */ UNIT ptp_unit = { - UDATA (&ptp_svc, UNIT_SEQ+UNIT_ATTABLE, 0), WPS / 20 }; + UDATA (&ptp_svc, UNIT_SEQ+UNIT_ATTABLE, 0), WPS / 20 + }; REG ptp_reg[] = { - { ORDATA (BUF, ptp_unit.buf, 8) }, - { 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 } }; + { ORDATA (BUF, ptp_unit.buf, 8) }, + { 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[] = { - { UNIT_FLEX_D, UNIT_FLEX_D, NULL, "FLEX", &tap_attable }, - { UNIT_FLEX_D, 0, NULL, "ASCII", &tap_attable }, - { UNIT_ATT+UNIT_FLEX, UNIT_ATT+UNIT_FLEX, - "file is Flex", NULL }, - { UNIT_ATT+UNIT_FLEX, UNIT_ATT, - "file is ASCII", NULL }, - { UNIT_ATTABLE+UNIT_ATT+UNIT_FLEX, UNIT_ATTABLE+UNIT_FLEX, - "default is Flex", NULL }, - { UNIT_ATTABLE+UNIT_ATT+UNIT_FLEX, UNIT_ATTABLE, - "default is ASCII", NULL }, - { 0, 0 } }; + { UNIT_FLEX_D, UNIT_FLEX_D, NULL, "FLEX", &tap_attable }, + { UNIT_FLEX_D, 0, NULL, "ASCII", &tap_attable }, + { UNIT_ATT+UNIT_FLEX, UNIT_ATT+UNIT_FLEX, + "file is Flex", NULL }, + { UNIT_ATT+UNIT_FLEX, UNIT_ATT, + "file is ASCII", NULL }, + { UNIT_ATTABLE+UNIT_ATT+UNIT_FLEX, UNIT_ATTABLE+UNIT_FLEX, + "default is Flex", NULL }, + { UNIT_ATTABLE+UNIT_ATT+UNIT_FLEX, UNIT_ATTABLE, + "default is ASCII", NULL }, + { 0 } + }; DEVICE ptp_dev = { - "PTP", &ptp_unit, ptp_reg, ptp_mod, - 1, 10, 31, 1, 16, 7, - NULL, NULL, &ptp_reset, - NULL, &tap_attach, NULL }; - + "PTP", &ptp_unit, ptp_reg, ptp_mod, + 1, 10, 31, 1, 16, 7, + NULL, NULL, &ptp_reset, + NULL, &tap_attach, NULL + }; + /* Input instruction */ void op_i_strt (uint32 dev) { -switch (dev) { /* case on device */ -case DEV_PT: /* ptr */ - sim_activate (&ptr_unit, ptr_unit.wait); /* activate */ - break; -case DEV_TT: /* tti/ttr */ - if (Q_MANI) sim_putchar ('`'); /* manual input? */ - else sim_activate (&tti_unit[1], tt_wait); /* no, must be ttr */ - break; } +switch (dev) { /* case on device */ + + case DEV_PT: /* ptr */ + sim_activate (&ptr_unit, ptr_unit.wait); /* activate */ + break; + + case DEV_TT: /* tti/ttr */ + if (Q_MANI) sim_putchar ('`'); /* manual input? */ + else sim_activate (&tti_unit[1], tt_wait); /* no, must be ttr */ + break; + } return; -} +} t_stat op_i (uint32 dev, uint32 ch, uint32 sh4) { -if (Q_LGP21 && out_strt) return STOP_STALL; /* LGP-21? must be idle */ -if (!inp_strt) { /* input started? */ - inp_strt = 1; /* no, set start */ - inp_done = 0; /* clear done */ - A = shift_in (A, ch, sh4); - tti_rdy = ptr_rdy = 0; /* no input */ - if (Q_LGP21 || Q_INPT) op_i_strt (dev); } /* LGP-21 or PTR? start */ +if (Q_LGP21 && out_strt) return STOP_STALL; /* LGP-21? must be idle */ +if (!inp_strt) { /* input started? */ + inp_strt = 1; /* no, set start */ + inp_done = 0; /* clear done */ + A = shift_in (A, ch, sh4); + tti_rdy = ptr_rdy = 0; /* no input */ + if (Q_LGP21 || Q_INPT) op_i_strt (dev); /* LGP-21 or PTR? start */ + } +switch (dev) { /* case on device */ -switch (dev) { /* case on device */ -case DEV_PT: /* ptr */ - if (ptr_rdy) { /* char ready? */ - ptr_rdy = 0; /* reset ready */ - if ((ptr_unit.buf != FLEX_DEL) && /* ignore delete and */ - (!Q_LGP21 || ((ptr_unit.buf & 3) == 2))) /* LGP-21 4b? zone != 2 */ - A = shift_in (A, ptr_unit.buf, sh4); } /* shift data in */ - break; -case DEV_TT: /* tti/ttr */ - if (tti_rdy) { /* char ready? */ - tti_rdy = 0; /* reset ready */ - if ((tti_buf != FLEX_DEL) && /* ignore delete and */ - (!Q_LGP21 || ((tti_buf & 3) != 0))) /* LGP-21 4b? zone == 0 */ - A = shift_in (A, tti_buf, sh4); } /* shift data in */ - break; -default: /* nx device */ - return STOP_NXDEV; } /* return error */ + case DEV_PT: /* ptr */ + if (ptr_rdy) { /* char ready? */ + ptr_rdy = 0; /* reset ready */ + if ((ptr_unit.buf != FLEX_DEL) && /* ignore delete and */ + (!Q_LGP21 || ((ptr_unit.buf & 3) == 2))) /* LGP-21 4b? zone != 2 */ + A = shift_in (A, ptr_unit.buf, sh4); /* shift data in */ + } + break; -if (inp_done) { /* done? */ - inp_strt = inp_done = 0; /* clear start, done */ - return SCPE_OK; } /* no stall */ -return STOP_STALL; /* stall */ + case DEV_TT: /* tti/ttr */ + if (tti_rdy) { /* char ready? */ + tti_rdy = 0; /* reset ready */ + if ((tti_buf != FLEX_DEL) && /* ignore delete and */ + (!Q_LGP21 || ((tti_buf & 3) != 0))) /* LGP-21 4b? zone == 0 */ + A = shift_in (A, tti_buf, sh4); /* shift data in */ + } + break; + + default: /* nx device */ + return STOP_NXDEV; /* return error */ + } + +if (inp_done) { /* done? */ + inp_strt = inp_done = 0; /* clear start, done */ + return SCPE_OK; /* no stall */ + } +return STOP_STALL; /* stall */ } +/* Terminal keyboard unit service */ + t_stat tti_svc (UNIT *uptr) { int32 c, flex; -sim_activate (uptr, tt_wait); /* continue poll */ -if ((c = sim_poll_kbd ()) < SCPE_KFLAG) return c; /* no char or error? */ -flex = ascii_to_flex[c & 0x1FF]; /* cvt to flex */ -if (flex > 0) { /* it's a typewriter... */ - write_tto (flex); /* always echos */ - if (tto_unit[1].flags & UNIT_ATT) /* ttp attached? */ - write_punch (&tto_unit[1], tto_buf); } /* punch to ttp */ -else write_tto ('\a'); /* don't echo bad */ -if (Q_MANI && (flex > 0) && flex_inp_valid[flex]) { /* wanted, valid? */ - if (flex == FLEX_CSTOP) inp_done = 1; /* conditional stop? */ - else tti_rdy = 1; /* no, set ready */ - tti_buf = flex; /* save char */ - uptr->pos = uptr->pos + 1; } +sim_activate (uptr, tt_wait); /* continue poll */ +if ((c = sim_poll_kbd ()) < SCPE_KFLAG) return c; /* no char or error? */ +flex = ascii_to_flex[c & 0x1FF]; /* cvt to flex */ +if (flex > 0) { /* it's a typewriter... */ + write_tto (flex); /* always echos */ + if (tto_unit[1].flags & UNIT_ATT) /* ttp attached? */ + write_punch (&tto_unit[1], tto_buf); /* punch to ttp */ + } +else write_tto ('\a'); /* don't echo bad */ +if (Q_MANI && (flex > 0) && flex_inp_valid[flex]) { /* wanted, valid? */ + if (flex == FLEX_CSTOP) inp_done = 1; /* conditional stop? */ + else tti_rdy = 1; /* no, set ready */ + tti_buf = flex; /* save char */ + uptr->pos = uptr->pos + 1; + } return SCPE_OK; } +/* Terminal reader unit service */ + t_stat ttr_svc (UNIT *uptr) { t_stat r; if (r = read_reader (uptr, ttr_stopioe, (int32 *) &tti_buf)) return r; -if (!(uptr->flags & UNIT_NOCS) && /* cstop enable? */ - (tti_buf == FLEX_CSTOP)) inp_done = 1; /* cond stop? */ -else { tti_rdy = 1; /* no, set ready */ - sim_activate (uptr, tt_wait); } /* cont reading */ -write_tto (tti_buf); /* echo to tto */ -if (tto_unit[1].flags & UNIT_ATT) /* ttp attached? */ - return write_punch (&tto_unit[1], tti_buf); /* punch to ttp */ +if (!(uptr->flags & UNIT_NOCS) && /* cstop enable? */ + (tti_buf == FLEX_CSTOP)) inp_done = 1; /* cond stop? */ +else { + tti_rdy = 1; /* no, set ready */ + sim_activate (uptr, tt_wait); /* cont reading */ + } +write_tto (tti_buf); /* echo to tto */ +if (tto_unit[1].flags & UNIT_ATT) /* ttp attached? */ + return write_punch (&tto_unit[1], tti_buf); /* punch to ttp */ return SCPE_OK; } +/* Paper tape reader unit service */ + t_stat ptr_svc (UNIT *uptr) { t_stat r; if (r = read_reader (uptr, ptr_stopioe, &uptr->buf)) return r; -if (uptr->buf == FLEX_CSTOP) inp_done = 1; /* cond stop? */ -else { ptr_rdy = 1; /* no, set ready */ - sim_activate (uptr, uptr->wait); } /* cont reading */ +if (uptr->buf == FLEX_CSTOP) inp_done = 1; /* cond stop? */ +else { + ptr_rdy = 1; /* no, set ready */ + sim_activate (uptr, uptr->wait); /* cont reading */ + } return SCPE_OK; } - + /* Output instruction */ t_stat op_p (uint32 dev, uint32 ch) { -switch (dev) { /* case on device */ -case DEV_PT: /* paper tape punch */ - if (sim_is_active (&ptp_unit)) /* busy? */ - return (Q_LGP21? STOP_STALL: SCPE_OK); /* LGP-21: stall */ - ptp_unit.buf = ch; /* save char */ - sim_activate (&ptp_unit, ptp_unit.wait); /* activate ptp */ - break; -case DEV_TT: /* typewriter */ - if (ch == 0) { /* start input? */ - if (!Q_LGP21 && !Q_INPT) /* ignore if LGP-21, ptr */ - op_i_strt (DEV_TT); /* start tti */ - return SCPE_OK; } /* no stall */ - if (sim_is_active (&tto_unit[0])) /* busy? */ - return (Q_LGP21? STOP_STALL: SCPE_OK); /* LGP-21: stall */ - tto_buf = ch; /* save char */ - sim_activate (&tto_unit[0], tt_wait); /* activate tto */ - break; -default: /* unknown */ - return STOP_NXDEV; } /* return error */ +switch (dev) { /* case on device */ -if (out_strt == 0) { /* output started? */ - out_strt = 1; /* flag start */ - out_done = 0; } /* clear done */ -return SCPE_OK; /* no stall */ + case DEV_PT: /* paper tape punch */ + if (sim_is_active (&ptp_unit)) /* busy? */ + return (Q_LGP21? STOP_STALL: SCPE_OK); /* LGP-21: stall */ + ptp_unit.buf = ch; /* save char */ + sim_activate (&ptp_unit, ptp_unit.wait); /* activate ptp */ + break; + + case DEV_TT: /* typewriter */ + if (ch == 0) { /* start input? */ + if (!Q_LGP21 && !Q_INPT) /* ignore if LGP-21, ptr */ + op_i_strt (DEV_TT); /* start tti */ + return SCPE_OK; /* no stall */ + } + if (sim_is_active (&tto_unit[0])) /* busy? */ + return (Q_LGP21? STOP_STALL: SCPE_OK); /* LGP-21: stall */ + tto_buf = ch; /* save char */ + sim_activate (&tto_unit[0], tt_wait); /* activate tto */ + break; + + default: /* unknown */ + return STOP_NXDEV; /* return error */ + } + +if (out_strt == 0) { /* output started? */ + out_strt = 1; /* flag start */ + out_done = 0; /* clear done */ + } +return SCPE_OK; /* no stall */ } -/* TTO unit service */ +/* Terminal printer unit service */ t_stat tto_svc (UNIT *uptr) { t_stat r; -if ((r = write_tto (tto_buf)) != SCPE_OK) { /* output; error? */ - sim_activate (uptr, tt_wait); /* try again */ - return ((r == SCPE_STALL)? SCPE_OK: r); } /* !stall? report */ +if ((r = write_tto (tto_buf)) != SCPE_OK) { /* output; error? */ + sim_activate (uptr, tt_wait); /* try again */ + return ((r == SCPE_STALL)? SCPE_OK: r); /* !stall? report */ + } out_strt = 0; out_done = 1; -if (tto_unit[1].flags & UNIT_ATT) /* ttp attached? */ - return write_punch (&tto_unit[1], tto_buf); /* punch to ttp */ +if (tto_unit[1].flags & UNIT_ATT) /* ttp attached? */ + return write_punch (&tto_unit[1], tto_buf); /* punch to ttp */ return SCPE_OK; } -/* PTP unit service */ +/* Paper tape punch unit service */ t_stat ptp_svc (UNIT *uptr) { out_strt = 0; out_done = 1; -if ((uptr->flags & UNIT_ATT) == 0) /* not attached? */ - return IORETURN (ptp_stopioe, SCPE_UNATT); /* error */ -return write_punch (uptr, uptr->buf); /* write to ptp */ +if ((uptr->flags & UNIT_ATT) == 0) /* not attached? */ + return IORETURN (ptp_stopioe, SCPE_UNATT); /* error */ +return write_punch (uptr, uptr->buf); /* write to ptp */ } - + /* Utility routines */ t_stat read_reader (UNIT *uptr, int32 stop, int32 *fl) { int32 ch, flex; -if ((uptr->flags & UNIT_ATT) == 0) /* attached? */ - return IORETURN (stop, SCPE_UNATT); -do { if ((ch = getc (uptr->fileref)) == EOF) { /* read char */ - if (feof (uptr->fileref)) { /* err or eof? */ - if (stop) printf ("Reader end of file\n"); - else return SCPE_OK; } - else perror ("Reader I/O error"); - clearerr (uptr->fileref); - return SCPE_IOERR; } - if (uptr->flags & UNIT_FLEX) /* transposed flex? */ - flex = ((ch << 1) | (ch >> 5)) & 0x3F; /* undo 612345 */ - else if (ch == '#') { /* encoded? */ - int32 d1 = getc (uptr->fileref); /* get 2 digits */ - int32 d2 = getc (uptr->fileref); - if ((d1 == EOF) || (d2 == EOF)) { /* error? */ - if (feof (uptr->fileref)) { /* eof? */ - if (stop) printf ("Reader end of file\n"); - else return SCPE_OK; } - else perror ("Reader I/O error"); - clearerr (uptr->fileref); - return SCPE_IOERR; } - flex = (((d1 - '0') * 10) + (d2 - '0')) & 0x3F; - uptr->pos = uptr->pos + 2; } - else flex = ascii_to_flex[ch & 0x7F]; /* convert */ - uptr->pos = uptr->pos + 1; } -while (flex < 0); /* until valid */ -*fl = flex; /* return char */ +if ((uptr->flags & UNIT_ATT) == 0) /* attached? */ + return IORETURN (stop, SCPE_UNATT); +do { + if ((ch = getc (uptr->fileref)) == EOF) { /* read char */ + if (feof (uptr->fileref)) { /* err or eof? */ + if (stop) printf ("Reader end of file\n"); + else return SCPE_OK; + } + else perror ("Reader I/O error"); + clearerr (uptr->fileref); + return SCPE_IOERR; + } + if (uptr->flags & UNIT_FLEX) /* transposed flex? */ + flex = ((ch << 1) | (ch >> 5)) & 0x3F; /* undo 612345 */ + else if (ch == '#') { /* encoded? */ + int32 d1 = getc (uptr->fileref); /* get 2 digits */ + int32 d2 = getc (uptr->fileref); + if ((d1 == EOF) || (d2 == EOF)) { /* error? */ + if (feof (uptr->fileref)) { /* eof? */ + if (stop) printf ("Reader end of file\n"); + else return SCPE_OK; + } + else perror ("Reader I/O error"); + clearerr (uptr->fileref); + return SCPE_IOERR; + } + flex = (((d1 - '0') * 10) + (d2 - '0')) & 0x3F; + uptr->pos = uptr->pos + 2; + } + else flex = ascii_to_flex[ch & 0x7F]; /* convert */ + uptr->pos = uptr->pos + 1; + } while (flex < 0); /* until valid */ +*fl = flex; /* return char */ return SCPE_OK; } @@ -472,16 +526,20 @@ t_stat write_tto (int32 flex) int32 ch; t_stat r; -if (flex == FLEX_UC) tto_uc = 1; /* UC? set state */ -else if (flex == FLEX_LC) tto_uc = 0; /* LC? set state */ -else { if (flex == FLEX_BS) ch = '\b'; /* backspace? */ - else ch = flex_to_ascii[flex | (tto_uc << 6)]; /* cvt flex to ascii */ - if (ch > 0) { /* legit? */ - if (r = sim_putchar_s (ch)) return r; /* write char */ - tto_unit[0].pos = tto_unit[0].pos + 1; - if (flex == FLEX_CR) { /* cr? */ - sim_putchar ('\n'); /* add lf */ - tto_unit[0].pos = tto_unit[0].pos + 1; } } } +if (flex == FLEX_UC) tto_uc = 1; /* UC? set state */ +else if (flex == FLEX_LC) tto_uc = 0; /* LC? set state */ +else { + if (flex == FLEX_BS) ch = '\b'; /* backspace? */ + else ch = flex_to_ascii[flex | (tto_uc << 6)]; /* cvt flex to ascii */ + if (ch > 0) { /* legit? */ + if (r = sim_putchar_s (ch)) return r; /* write char */ + tto_unit[0].pos = tto_unit[0].pos + 1; + if (flex == FLEX_CR) { /* cr? */ + sim_putchar ('\n'); /* add lf */ + tto_unit[0].pos = tto_unit[0].pos + 1; + } + } + } return SCPE_OK; } @@ -489,19 +547,20 @@ t_stat write_punch (UNIT *uptr, int32 flex) { int32 c, sta; -if (uptr->flags & UNIT_FLEX) /* transposed flex? */ - c = ((flex >> 1) | (flex << 5)) & 0x3F; /* reorder to 612345 */ -else c = flex_to_ascii[flex]; /* convert to ASCII */ -if (c >= 0) sta = fputc (c, uptr->fileref); /* valid? */ -else sta = fprintf (uptr->fileref, "#%02d", flex); /* no, encode */ -if (sta == EOF) { /* error? */ - perror ("Punch I/O error"); /* error? */ - clearerr (uptr->fileref); - return SCPE_IOERR; } -uptr->pos = uptr->pos + ((c >= 0)? 1: 3); /* incr position */ +if (uptr->flags & UNIT_FLEX) /* transposed flex? */ + c = ((flex >> 1) | (flex << 5)) & 0x3F; /* reorder to 612345 */ +else c = flex_to_ascii[flex]; /* convert to ASCII */ +if (c >= 0) sta = fputc (c, uptr->fileref); /* valid? */ +else sta = fprintf (uptr->fileref, "#%02d", flex); /* no, encode */ +if (sta == EOF) { /* error? */ + perror ("Punch I/O error"); /* error? */ + clearerr (uptr->fileref); + return SCPE_IOERR; + } +uptr->pos = uptr->pos + ((c >= 0)? 1: 3); /* incr position */ return SCPE_OK; } - + /* Reset routines */ t_stat tti_reset (DEVICE *dptr) @@ -545,7 +604,7 @@ t_stat r; if ((r = attach_unit (uptr,cptr)) != SCPE_OK) return r; if ((sim_switches & SWMASK ('F')) || ((uptr->flags & UNIT_FLEX_D) && !(sim_switches & SWMASK ('A')))) - uptr->flags = uptr->flags | UNIT_FLEX; + uptr->flags = uptr->flags | UNIT_FLEX; else uptr->flags = uptr->flags & ~UNIT_FLEX; return SCPE_OK; } @@ -563,8 +622,9 @@ return SCPE_NOFNC; t_stat tti_rdrss (UNIT *uptr, int32 val, char *cptr, void *desc) { if (val) { - if ((tti_unit[1].flags & UNIT_ATT) == 0) return SCPE_UNATT; - sim_activate (&tti_unit[1], tt_wait); } + if ((tti_unit[1].flags & UNIT_ATT) == 0) return SCPE_UNATT; + sim_activate (&tti_unit[1], tt_wait); + } else sim_cancel (&tti_unit[1]); return SCPE_OK; } @@ -578,12 +638,14 @@ t_stat r; if ((uptr->flags & UNIT_ATT) == 0) return SCPE_UNATT; if (cptr) { - cnt = (int32) get_uint (cptr, 10, 512, &r); - if ((r != SCPE_OK) || (cnt == 0)) return SCPE_ARG; } + cnt = (int32) get_uint (cptr, 10, 512, &r); + if ((r != SCPE_OK) || (cnt == 0)) return SCPE_ARG; + } else cnt = 10; while (cnt-- > 0) { - r = write_punch (uptr, 0); - if (r != SCPE_OK) return r; } + r = write_punch (uptr, 0); + if (r != SCPE_OK) return r; + } return SCPE_OK; } diff --git a/LGP/lgp_sys.c b/LGP/lgp_sys.c index a4d22080..e52c5ff1 100644 --- a/LGP/lgp_sys.c +++ b/LGP/lgp_sys.c @@ -19,11 +19,11 @@ 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 + 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-Jan-05 RMS Modified VM pointer setup + 04-Jan-05 RMS Modified VM pointer setup */ #include "lgp_defs.h" @@ -48,12 +48,12 @@ extern t_addr (*sim_vm_parse_addr) (DEVICE *dptr, char *cptr, char **tptr); /* 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 + 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[] = "LGP30"; @@ -63,34 +63,36 @@ REG *sim_PC = &cpu_reg[0]; int32 sim_emax = 1; DEVICE *sim_devices[] = { - &cpu_dev, - &tti_dev, - &tto_dev, - &ptr_dev, - &ptp_dev, - NULL }; + &cpu_dev, + &tti_dev, + &tto_dev, + &ptr_dev, + &ptp_dev, + NULL + }; const char *sim_stop_messages[] = { - "Unknown error", - "STOP", - "Breakpoint", - "Arithmetic overflow" }; - + "Unknown error", + "STOP", + "Breakpoint", + "Arithmetic overflow" + }; + /* Binary loader - implements a restricted form of subroutine 10.4 Switches: - -t, input file is transposed Flex - -n, no checksums on v commands (10.0 compatible) - default is ASCII encoded Flex + -t, input file is transposed Flex + -n, no checksums on v commands (10.0 compatible) + default is ASCII encoded Flex Commands (in bits 0-3): - (blank) instruction - + command (not supported) - ; start fill - / set modifier - . stop and transfer - , hex words - v hex fill (checksummed unless -n) - 8 negative instruction + (blank) instruction + + command (not supported) + ; start fill + / set modifier + . stop and transfer + , hex words + v hex fill (checksummed unless -n) + 8 negative instruction */ /* Utility routine - read characters until ' (conditional stop) */ @@ -101,14 +103,15 @@ int32 flex, c; *wd = 0; while ((c = fgetc (fi)) != EOF) { - if (sim_switches & SWMASK ('T')) - flex = ((c << 1) | (c >> 5)) & 0x3F; - else flex = ascii_to_flex[c & 0x7F]; - if ((flex == FLEX_CR) || (flex == FLEX_DEL) || - (flex == FLEX_UC) || (flex == FLEX_LC) || - (flex == FLEX_BS) || (flex < 0)) continue; - if (flex == FLEX_CSTOP) return SCPE_OK; - *wd = (*wd << 4) | ((flex >> 2) & 0xF); } + if (sim_switches & SWMASK ('T')) + flex = ((c << 1) | (c >> 5)) & 0x3F; + else flex = ascii_to_flex[c & 0x7F]; + if ((flex == FLEX_CR) || (flex == FLEX_DEL) || + (flex == FLEX_UC) || (flex == FLEX_LC) || + (flex == FLEX_BS) || (flex < 0)) continue; + if (flex == FLEX_CSTOP) return SCPE_OK; + *wd = (*wd << 4) | ((flex >> 2) & 0xF); + } return SCPE_FMT; } @@ -137,59 +140,70 @@ t_stat sim_load (FILE *fi, char *cptr, char *fnam, int flag) uint32 wd, origin, amod, csum, cnt, tr, sc, ad, cmd; origin = amod = 0; -for (;;) { /* until stopped */ - if (load_getw (fi, &wd)) break; /* get ctrl word */ - cmd = (wd >> 28) & 0xF; /* get <0:3> */ - switch (cmd) { /* decode <0:3> */ - case 0x2: /* + command */ - return SCPE_FMT; - case 0x3: /* ; start fill */ - if (load_geta (wd, &origin)) return SCPE_FMT; /* origin = addr */ - break; - case 0x4: /* / set modifier */ - if (load_geta (wd, &amod)) return SCPE_FMT; /* modifier = addr */ - break; - case 0x5: /* . transfer */ - if (load_geta (wd, &PC)) return SCPE_FMT; /* PC = addr */ - return SCPE_OK; /* done! */ - case 0x6: /* hex words */ - if (load_geta (wd, &cnt)) return SCPE_FMT; /* count = addr */ - if ((cnt == 0) || (cnt > 63)) return SCPE_FMT; - while (cnt--) { /* fill hex words */ - if (load_getw (fi, &wd)) return SCPE_FMT; - Write (origin, wd); - origin = (origin + 1) & AMASK; } - break; - case 0x7: /* hex fill */ - cnt = (wd >> 16) & 0xFFF; /* hex count */ - tr = (wd >> 8) & 0xFF; /* hex track */ - sc = wd & 0xFF; /* hex sector */ - if ((cnt == 0) || (cnt > 0x7FF) || /* validate */ - (tr >= NTK_30) || (sc >= NSC_30)) return SCPE_ARG; - ad = (tr * NSC_30) + sc; /* decimal addr */ - for (csum = 0; cnt; cnt--) { /* fill words */ - if (load_getw (fi, &wd)) return SCPE_FMT; - Write (ad, wd); - csum = (csum + wd) & MMASK; - ad = (ad + 1) & AMASK; } - if (!(sim_switches & SWMASK ('N'))) { /* unless -n, csum */ - if (load_getw (fi, &wd)) return SCPE_FMT; -/* if ((csum ^wd) & MMASK) return SCPE_CSUM; */ } - break; - case 0x0: case 0x8: /* instructions */ - if (load_geta (wd, &ad)) return SCPE_FMT; /* get address */ - if ((wd & 0x00F00000) != 0x00900000) /* if not x, */ - ad = (ad + amod) & AMASK; /* modify */ - wd = (wd & (SIGN|I_OP)) + (ad << I_V_EA); /* instruction */ - default: /* data word */ - Write (origin, wd); - origin = (origin + 1) & AMASK; - break; - } /* end case */ - } /* end for */ +for (;;) { /* until stopped */ + if (load_getw (fi, &wd)) break; /* get ctrl word */ + cmd = (wd >> 28) & 0xF; /* get <0:3> */ + switch (cmd) { /* decode <0:3> */ + + case 0x2: /* + command */ + return SCPE_FMT; + + case 0x3: /* ; start fill */ + if (load_geta (wd, &origin)) return SCPE_FMT; /* origin = addr */ + break; + + case 0x4: /* / set modifier */ + if (load_geta (wd, &amod)) return SCPE_FMT; /* modifier = addr */ + break; + + case 0x5: /* . transfer */ + if (load_geta (wd, &PC)) return SCPE_FMT; /* PC = addr */ + return SCPE_OK; /* done! */ + + case 0x6: /* hex words */ + if (load_geta (wd, &cnt)) return SCPE_FMT; /* count = addr */ + if ((cnt == 0) || (cnt > 63)) return SCPE_FMT; + while (cnt--) { /* fill hex words */ + if (load_getw (fi, &wd)) return SCPE_FMT; + Write (origin, wd); + origin = (origin + 1) & AMASK; + } + break; + + case 0x7: /* hex fill */ + cnt = (wd >> 16) & 0xFFF; /* hex count */ + tr = (wd >> 8) & 0xFF; /* hex track */ + sc = wd & 0xFF; /* hex sector */ + if ((cnt == 0) || (cnt > 0x7FF) || /* validate */ + (tr >= NTK_30) || (sc >= NSC_30)) return SCPE_ARG; + ad = (tr * NSC_30) + sc; /* decimal addr */ + for (csum = 0; cnt; cnt--) { /* fill words */ + if (load_getw (fi, &wd)) return SCPE_FMT; + Write (ad, wd); + csum = (csum + wd) & MMASK; + ad = (ad + 1) & AMASK; + } + if (!(sim_switches & SWMASK ('N'))) { /* unless -n, csum */ + if (load_getw (fi, &wd)) return SCPE_FMT; +/* if ((csum ^wd) & MMASK) return SCPE_CSUM; */ + } + break; + + case 0x0: case 0x8: /* instructions */ + if (load_geta (wd, &ad)) return SCPE_FMT; /* get address */ + if ((wd & 0x00F00000) != 0x00900000) /* if not x, */ + ad = (ad + amod) & AMASK; /* modify */ + wd = (wd & (SIGN|I_OP)) + (ad << I_V_EA); /* instruction */ + + default: /* data word */ + Write (origin, wd); + origin = (origin + 1) & AMASK; + break; + } /* end case */ + } /* end for */ return SCPE_OK; } - + /* Symbol tables */ static const char opcode[] = "ZBYRIDNMPEUTHCAS"; @@ -199,9 +213,9 @@ static const char hex_decode[] = "0123456789FGJKQW"; void lgp_fprint_addr (FILE *st, DEVICE *dptr, t_addr addr) { if ((dptr == sim_devices[0]) && - ((sim_switches & SWMASK ('T')) || - ((cpu_unit.flags & UNIT_TTSS_D) && !(sim_switches & SWMASK ('N'))))) - fprintf (st, "%02d%02d", addr >> 6, addr & SCMASK_30); + ((sim_switches & SWMASK ('T')) || + ((cpu_unit.flags & UNIT_TTSS_D) && !(sim_switches & SWMASK ('N'))))) + fprintf (st, "%02d%02d", addr >> 6, addr & SCMASK_30); else fprint_val (st, addr, dptr->aradix, dptr->awidth, PV_LEFT); return; } @@ -211,13 +225,15 @@ t_addr lgp_parse_addr (DEVICE *dptr, char *cptr, char **tptr) t_addr ad, ea; if ((dptr == sim_devices[0]) && - ((sim_switches & SWMASK ('T')) || - ((cpu_unit.flags & UNIT_TTSS_D) && !(sim_switches & SWMASK ('N'))))) { - ad = (t_addr) strtotv (cptr, tptr, 10); - if (((ad / 100) >= NTK_30) || ((ad % 100) >= NSC_30)) { - *tptr = cptr; - return 0; } - ea = ((ad / 100) * NSC_30) | (ad % 100); } + ((sim_switches & SWMASK ('T')) || + ((cpu_unit.flags & UNIT_TTSS_D) && !(sim_switches & SWMASK ('N'))))) { + ad = (t_addr) strtotv (cptr, tptr, 10); + if (((ad / 100) >= NTK_30) || ((ad % 100) >= NSC_30)) { + *tptr = cptr; + return 0; + } + ea = ((ad / 100) * NSC_30) | (ad % 100); + } else ea = (t_addr) strtotv (cptr, tptr, dptr->aradix); return ea; } @@ -228,64 +244,69 @@ sim_vm_fprint_addr = &lgp_fprint_addr; sim_vm_parse_addr = &lgp_parse_addr; return; } - + /* Symbolic decode Inputs: - *of = output stream - addr = current PC - *val = pointer to data - *uptr = pointer to unit - sw = switches + *of = output stream + addr = current PC + *val = pointer to data + *uptr = pointer to unit + sw = switches Outputs: - return = status code + return = status code */ t_stat fprint_sym (FILE *of, t_addr addr, t_value *val, - UNIT *uptr, int32 sw) + UNIT *uptr, int32 sw) { int32 i, c; uint32 inst, op, ea; inst = val[0]; -if (sw & SWMASK ('A')) { /* alphabetic? */ - if ((uptr == NULL) || !(uptr->flags & UNIT_ATT)) return SCPE_ARG; - if (uptr->flags & UNIT_FLEX) { /* Flex file? */ - c = flex_to_ascii[inst]; /* get ASCII equiv */ - if (c <= 0) return SCPE_ARG; } - else c = inst & 0x7F; /* ASCII file */ - fputc (c, of); - return SCPE_OK; } +if (sw & SWMASK ('A')) { /* alphabetic? */ + if ((uptr == NULL) || !(uptr->flags & UNIT_ATT)) return SCPE_ARG; + if (uptr->flags & UNIT_FLEX) { /* Flex file? */ + c = flex_to_ascii[inst]; /* get ASCII equiv */ + if (c <= 0) return SCPE_ARG; + } + else c = inst & 0x7F; /* ASCII file */ + fputc (c, of); + return SCPE_OK; + } -if (uptr && (uptr != &cpu_unit)) return SCPE_ARG; /* must be CPU */ -if ((sw & SWMASK ('M')) && /* symbolic decode? */ +if (uptr && (uptr != &cpu_unit)) return SCPE_ARG; /* must be CPU */ +if ((sw & SWMASK ('M')) && /* symbolic decode? */ ((inst & ~(SIGN|I_OP|I_EA)) == 0)) { op = I_GETOP (inst); - ea = I_GETEA (inst); - if (inst & SIGN) fputc ('-', of); - fprintf (of, "%c ", opcode[op]); - lgp_fprint_addr (of, sim_devices[0], ea); - return SCPE_OK; } + ea = I_GETEA (inst); + if (inst & SIGN) fputc ('-', of); + fprintf (of, "%c ", opcode[op]); + lgp_fprint_addr (of, sim_devices[0], ea); + return SCPE_OK; + } -if ((sw & SWMASK ('L')) || /* LGP hex? */ +if ((sw & SWMASK ('L')) || /* LGP hex? */ ((cpu_unit.flags & UNIT_LGPH_D) && !(sw & SWMASK ('H')))) { - for (i = 0; i < 8; i++) { - c = (inst >> (4 * (7 - i))) & 0xF; - fputc (hex_decode[c], of); } - return SCPE_OK; } + for (i = 0; i < 8; i++) { + c = (inst >> (4 * (7 - i))) & 0xF; + fputc (hex_decode[c], of); + } + return SCPE_OK; + } 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 + *cptr = pointer to input string + addr = current PC + *uptr = pointer to unit + *val = pointer to output values + sw = switches Outputs: - status = error status + status = error status */ t_stat parse_sym (char *cptr, t_addr addr, UNIT *uptr, t_value *val, int32 sw) @@ -293,30 +314,34 @@ t_stat parse_sym (char *cptr, t_addr addr, UNIT *uptr, t_value *val, int32 sw) int32 i, c; char *tptr; -while (isspace (*cptr)) cptr++; /* absorb spaces */ +while (isspace (*cptr)) cptr++; /* absorb spaces */ if ((sw & SWMASK ('A')) || ((*cptr == '\'') && cptr++)) { - if ((uptr == NULL) || !(uptr->flags & UNIT_ATT)) return SCPE_ARG; - if (uptr->flags & UNIT_FLEX) { /* Flex file? */ - c = ascii_to_flex[*cptr & 0x7F]; /* get Flex equiv */ - if (c < 0) return SCPE_ARG; - val[0] = ((c >> 1) | (c << 5)) & 0x3F; } /* transpose */ - else val[0] = *cptr & 0x7F; /* ASCII file */ - return SCPE_OK; } + if ((uptr == NULL) || !(uptr->flags & UNIT_ATT)) return SCPE_ARG; + if (uptr->flags & UNIT_FLEX) { /* Flex file? */ + c = ascii_to_flex[*cptr & 0x7F]; /* get Flex equiv */ + if (c < 0) return SCPE_ARG; + val[0] = ((c >> 1) | (c << 5)) & 0x3F; /* transpose */ + } + else val[0] = *cptr & 0x7F; /* ASCII file */ + return SCPE_OK; + } -if (uptr && (uptr != &cpu_unit)) return SCPE_ARG; /* must be CPU */ -if (!parse_sym_m (cptr, val, sw)) return SCPE_OK; /* symbolic parse? */ -if ((sw & SWMASK ('L')) || /* LGP hex? */ +if (uptr && (uptr != &cpu_unit)) return SCPE_ARG; /* must be CPU */ +if (!parse_sym_m (cptr, val, sw)) return SCPE_OK; /* symbolic parse? */ +if ((sw & SWMASK ('L')) || /* LGP hex? */ ((cpu_unit.flags & UNIT_LGPH_D) && !(sw & SWMASK ('H')))) { - val[0] = 0; - while (isspace (*cptr)) cptr++; /* absorb spaces */ - for (i = 0; i < 8; i++) { - c = *cptr++; /* get char */ - if (c == 0) return SCPE_OK; - if (islower (c)) c = toupper (c); - if (tptr = strchr (hex_decode, c)) - val[0] = (val[0] << 4) | (tptr - hex_decode); - else return SCPE_ARG; } - if (*cptr == 0) return SCPE_OK; } + val[0] = 0; + while (isspace (*cptr)) cptr++; /* absorb spaces */ + for (i = 0; i < 8; i++) { + c = *cptr++; /* get char */ + if (c == 0) return SCPE_OK; + if (islower (c)) c = toupper (c); + if (tptr = strchr (hex_decode, c)) + val[0] = (val[0] << 4) | (tptr - hex_decode); + else return SCPE_ARG; + } + if (*cptr == 0) return SCPE_OK; + } return SCPE_ARG; } @@ -328,19 +353,20 @@ uint32 ea, sgn; char *tptr, gbuf[CBUFSIZE]; if (*cptr == '-') { - cptr++; - sgn = SIGN; } + cptr++; + sgn = SIGN; + } else sgn = 0; -cptr = get_glyph (cptr, gbuf, 0); /* get opcode */ +cptr = get_glyph (cptr, gbuf, 0); /* get opcode */ if (gbuf[1] != 0) return SCPE_ARG; if (tptr = strchr (opcode, gbuf[0])) - val[0] = ((tptr - opcode) << I_V_OP) | sgn; /* merge opcode */ + val[0] = ((tptr - opcode) << I_V_OP) | sgn; /* merge opcode */ else return SCPE_ARG; -cptr = get_glyph (cptr, gbuf, 0); /* get address */ +cptr = get_glyph (cptr, gbuf, 0); /* get address */ ea = lgp_parse_addr (sim_devices[0], gbuf, &tptr); if ((tptr == gbuf) || (*tptr != 0) || (ea > AMASK)) - return SCPE_ARG; -val[0] = val[0] | (ea << I_V_EA); /* merge address */ + return SCPE_ARG; +val[0] = val[0] | (ea << I_V_EA); /* merge address */ if (*cptr != 0) return SCPE_2MARG; return SCPE_OK; } diff --git a/NOVA/eclipse.txt b/NOVA/eclipse.txt index 4cc9cf08..de753a4c 100644 --- a/NOVA/eclipse.txt +++ b/NOVA/eclipse.txt @@ -21,4 +21,4 @@ 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 +Windows or OS/2. diff --git a/NOVA/eclipse_cpu.c b/NOVA/eclipse_cpu.c index f5e5405e..f07b79c8 100644 --- a/NOVA/eclipse_cpu.c +++ b/NOVA/eclipse_cpu.c @@ -2,7 +2,7 @@ Modified from the original NOVA simulator by Robert Supnik. - Copyright (c) 1998-2002, Charles E Owen + Copyright (c) 1998-2005, Charles E Owen Portions Copyright (c) 1993-2002, Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a @@ -22,31 +22,32 @@ 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 + 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 + cpu Eclipse central processor - 29-Nov-03 CEO Corrected POPJ and Bit operations bugs - 26-Nov-03 CEO Added FPU and PIT devices - 20-Feb-03 CEO Corrected several MMPU and CIS bugs - 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 + 25-Aug-05 RMS Fixed DIVS overflow cases + 29-Nov-03 CEO Corrected POPJ and Bit operations bugs + 26-Nov-03 CEO Added FPU and PIT devices + 20-Feb-03 CEO Corrected several MMPU and CIS bugs + 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 + AC[0:3]<0:15> general registers + C carry flag + PC<0:14> program counter Eclipses with Folating Point Units added these registers: - FPAC[0:3]<0:63> Floating Point Accumulators - FPSR Floating Point Status Register + FPAC[0:3]<0:63> Floating Point Accumulators + FPSR Floating Point Status Register In addition, certain low-memory locations are reserved for special purposes: @@ -58,19 +59,19 @@ 4: VECTOR stack pointer (VCT Instruction) 5: Current Interrupt Priority mask 6: VECTOR stack limit (VCT instruction) - 7: VECTOR stack fault address (VCT again) + 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. + 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 @@ -150,28 +151,28 @@ 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| op | AC |in| mode| displacement | memory reference +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - <0:4> mnemonic action + <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 + 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 + <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>)] + 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 @@ -180,13 +181,12 @@ 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: + + 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 + | 0 1 1| AC | opcode |pulse| device | I/O transfer +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ The IOT instruction sends the opcode, pulse, and specified AC to the @@ -197,35 +197,34 @@ 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 + | 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) + | | | | | | +--- 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. + + 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. @@ -234,18 +233,18 @@ 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 + 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 + 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 @@ -259,9 +258,9 @@ 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_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 */ /*--------------------------------------------------------------------------- @@ -285,14 +284,14 @@ ** 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 +** 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 "show" 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. To -** dump history, enter the command "show cpu history", with -** the file "history" spelled correctly and lower case. +** dump history, enter the command "show cpu history", with +** the file "history" spelled correctly and lower case. ** ** XXXXDD = Log all I/O instructions to or from device number ** DD. Log is written to "trace.log", regardless of the @@ -307,7 +306,7 @@ ** 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 +** 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. @@ -335,46 +334,46 @@ #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_UP (UNIT_V_UF) /* FPU Enabled */ -#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_UP (1 << UNIT_V_UP) -#define UNIT_MSIZE (1 << UNIT_V_MSIZE) +#define UNIT_V_MICRO (UNIT_V_UF) /* Microeclipse? */ +#define UNIT_V_17B (UNIT_V_UF) /* 17 bit MAP */ +#define UNIT_V_UP (UNIT_V_UF) /* FPU Enabled */ +#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_UP (1 << UNIT_V_UP) +#define UNIT_MSIZE (1 << UNIT_V_MSIZE) -uint16 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 = 140; /* Model of Eclipse */ -int32 speed = 0; /* Delay for each instruction */ +uint16 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 = 140; /* 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 XCT_mode = 0; /* 1 if XCT mode */ +int32 XCT_inst = 0; /* XCT instruction */ int32 PPC = -1; -struct ndev dev_table[64]; /* dispatch table */ +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 */ +int32 hnext = 0; /* # of current entry */ +int32 hwrap = 0; /* 1 if wrapped */ +int32 hmax = HISTMAX; /* Maximum entries b4 wrap */ uint16 hpc[HISTMAX]; uint16 hinst[HISTMAX]; uint16 hinst2[HISTMAX]; @@ -384,20 +383,20 @@ uint16 hac2[HISTMAX]; uint16 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 - 0x40 - LEF mode was on - 0x80 - this is an int, not an inst. - hpc is return addr - hinst is int_req - hac0 is device - hac1 is int addr +/* Flags: 0x01 - carry bit + 0x02 - int enabled + 0x04 - user map a + 0x08 - user map b + 0x10 - user map c + 0x20 - user map d + 0x40 - LEF mode was on + 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 @@ -417,50 +416,50 @@ unsigned short hflags[HISTMAX]; */ -#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 */ +#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 */ /* The Eclipse Floating Point Unit: This unit is optional on all Eclipse models. */ -int32 FPSR = 0; /* 32-bit FPU Status Register */ -t_int64 FPAC[4] = { 0,0,0,0 }; /* 4 64-bit Accumulators */ -int32 FPFault = 0; /* Save Fault State */ +int32 FPSR = 0; /* 32-bit FPU Status Register */ +t_int64 FPAC[4] = { 0,0,0,0 }; /* 4 64-bit Accumulators */ +int32 FPFault = 0; /* Save Fault State */ /* Definitions for internal floating point arithmetic */ typedef struct _SHORT_FLOAT { - int32 short_fract; /* Fraction */ - short expo; /* Exponent + 64 */ - uint8 sign; /* Sign */ + int32 short_fract; /* Fraction */ + short expo; /* Exponent + 64 */ + uint8 sign; /* Sign */ } SHORT_FLOAT; typedef struct _LONG_FLOAT { - t_int64 long_fract; /* Fraction */ - short expo; /* Exponent + 64 */ - uint8 sign; /* Sign */ + t_int64 long_fract; /* Fraction */ + short expo; /* Exponent + 64 */ + uint8 sign; /* Sign */ } LONG_FLOAT; -LONG_FLOAT dfl,dfl2; /* Double Precision Work Fields */ -SHORT_FLOAT sfl,sfl2; /* Single Precision Work Fields */ -t_int64 tempfp, holdfp; /* Working area for FPAC */ -int shift,m3; +LONG_FLOAT dfl,dfl2; /* Double Precision Work Fields */ +SHORT_FLOAT sfl,sfl2; /* Single Precision Work Fields */ +t_int64 tempfp, holdfp; /* Working area for FPAC */ +int shift,m3; t_int64 lsfract; void get_sf(SHORT_FLOAT *fl, t_int64 *fpr); @@ -484,16 +483,16 @@ int div_lf(LONG_FLOAT *fl, LONG_FLOAT *div_fl); /* Special Debugging Info */ -int32 Debug_Flags = 0; /* Debug register - selects debug features */ -int32 Debug_Char = 0; /* Debug Character Register */ +int32 Debug_Flags = 0; /* Debug register - selects debug features */ +int32 Debug_Char = 0; /* Debug Character Register */ -int32 Tron = 0; /* For trace files */ +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 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); @@ -514,153 +513,161 @@ int32 Debug_Entry(int32 PC, int32 inst, int32 inst2, int32 AC0, int32 AC1, int32 t_stat build_devtab (void); extern t_stat fprint_sym (FILE *of, t_addr addr, t_value *val, - UNIT *uptr, int32 sw); - + 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 + 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) }; +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) }, - { ORDATA (DCHAR, Debug_Char, 16) }, - { DRDATA (MODEL, model, 16) }, - { DRDATA (SPEED, speed, 16) }, - { ORDATA (WRU, sim_int_char, 8) }, - { NULL } }; + { 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) }, + { ORDATA (DCHAR, Debug_Char, 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 }, - { MTAB_XTD|MTAB_VDV|MTAB_NMO, 0, "HISTORY", NULL, - NULL, &Dump_History }, - { 0 } }; + { 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 }, + { MTAB_XTD|MTAB_VDV|MTAB_NMO, 0, "HISTORY", NULL, + NULL, &Dump_History }, + { 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 }; + "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 + 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 } }; + { 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 } }; + { 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 }; + "MAP", &map_unit, map_reg, map_mod, + 1, 8, 17, 1, 8, 16, + &map_ex, &map_dep, NULL, + NULL, NULL, NULL +}; /* FPU data structures - fpu_dev MAP device descriptor - fpu_unit MAP unit descriptor - fpu_reg MAP register list - fpu_mod MAP modifiers list + fpu_dev MAP device descriptor + fpu_unit MAP unit descriptor + fpu_reg MAP register list + fpu_mod MAP modifiers list */ UNIT fpu_unit = { UDATA (&fpu_svc, UNIT_UP, MAXMEMSIZE) }; REG fpu_reg[] = { - { ORDATA (STATUS, FPSR, 32) }, - { ORDATA (FPAC0, FPAC[0], 64) }, - { ORDATA (FPAC1, FPAC[1], 64) }, - { ORDATA (FPAC2, FPAC[2], 64) }, - { ORDATA (FPAC3, FPAC[3], 64) }, - { ORDATA (FAULT, FPFault, 32) }, - { NULL } }; + { ORDATA (STATUS, FPSR, 32) }, + { ORDATA (FPAC0, FPAC[0], 64) }, + { ORDATA (FPAC1, FPAC[1], 64) }, + { ORDATA (FPAC2, FPAC[2], 64) }, + { ORDATA (FPAC3, FPAC[3], 64) }, + { ORDATA (FAULT, FPFault, 32) }, + { NULL } +}; MTAB fpu_mod[] = { - { UNIT_UP, UNIT_UP, "Enabled (UP)", "UP", NULL }, - { UNIT_UP, 0, "Disabled (DOWN)", "DOWN", NULL }, - { 0 } }; + { UNIT_UP, UNIT_UP, "Enabled (UP)", "UP", NULL }, + { UNIT_UP, 0, "Disabled (DOWN)", "DOWN", NULL }, + { 0 } +}; DEVICE fpu_dev = { - "FPU", &fpu_unit, fpu_reg, fpu_mod, - 1, 16, 17, 1, 16, 16, - NULL, NULL, NULL, - NULL, NULL, NULL }; + "FPU", &fpu_unit, fpu_reg, fpu_mod, + 1, 16, 17, 1, 16, 16, + NULL, NULL, NULL, + NULL, NULL, NULL +}; /* ---- Programmable Interval Timer Device ----------- */ int32 pit_time = 100; -int32 pit_tps = 10000; /* ticks per sec */ -int32 pit_adj = 20; /* tmxr adjust */ -int32 pit_poll = 16000; /* tmxr poll */ -int32 pit_initial = 0; /* initial counter reg */ -int32 pit_counter = 0; /* Counter */ -int32 pit_flag = 0; /* Initial setting flag */ +int32 pit_tps = 10000; /* ticks per sec */ +int32 pit_adj = 20; /* tmxr adjust */ +int32 pit_poll = 16000; /* tmxr poll */ +int32 pit_initial = 0; /* initial counter reg */ +int32 pit_counter = 0; /* Counter */ +int32 pit_flag = 0; /* Initial setting flag */ int32 pit (int32 pulse, int32 code, int32 AC); t_stat pit_svc (UNIT *uptr); t_stat pit_reset (DEVICE *dptr); - + /* PIT data structures - pit_dev device descriptor - pit_unit unit descriptor - pit_reg register list + pit_dev device descriptor + pit_unit unit descriptor + pit_reg register list */ DIB pit_dib = { DEV_PIT, INT_PIT, PI_PIT, &pit }; @@ -668,23 +675,24 @@ DIB pit_dib = { DEV_PIT, INT_PIT, PI_PIT, &pit }; UNIT pit_unit = { UDATA (&pit_svc, 0, 0) }; REG pit_reg[] = { - { ORDATA (INIT, pit_initial, 16) }, - { ORDATA (COUNT, pit_counter, 16) }, - { FLDATA (BUSY, dev_busy, INT_V_PIT) }, - { FLDATA (DONE, dev_done, INT_V_PIT) }, - { FLDATA (DISABLE, dev_disable, INT_V_PIT) }, - { FLDATA (INT, int_req, INT_V_PIT) }, - { DRDATA (TIME0, pit_time, 24), REG_NZ + PV_LEFT }, - { NULL } }; + { ORDATA (INIT, pit_initial, 16) }, + { ORDATA (COUNT, pit_counter, 16) }, + { FLDATA (BUSY, dev_busy, INT_V_PIT) }, + { FLDATA (DONE, dev_done, INT_V_PIT) }, + { FLDATA (DISABLE, dev_disable, INT_V_PIT) }, + { FLDATA (INT, int_req, INT_V_PIT) }, + { DRDATA (TIME0, pit_time, 24), REG_NZ + PV_LEFT }, + { NULL } +}; DEVICE pit_dev = { - "PIT", &pit_unit, pit_reg, NULL, - 1, 0, 0, 0, 0, 0, - NULL, NULL, &pit_reset, - NULL, NULL, NULL, - &pit_dib, 0 }; - - + "PIT", &pit_unit, pit_reg, NULL, + 1, 0, 0, 0, 0, 0, + NULL, NULL, &pit_reset, + NULL, NULL, NULL, + &pit_dib, 0 +}; + t_stat sim_instr (void) { extern int32 sim_interval; @@ -714,14 +722,14 @@ int32 pushrtn(int32 pc); /* Restore register state */ -if (build_devtab () != SCPE_OK) return SCPE_IERR; /* build dispatch */ -PC = saved_PC & AMASK; /* load local PC */ +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 */ +mask_out (pimask); /* reset int system */ reason = 0; if (MapInit == 0) { MapInit = 1; - for (mi1 = 0; mi1 < 6; mi1++) { /* Initialize MAPs */ + for (mi1 = 0; mi1 < 6; mi1++) { /* Initialize MAPs */ for (mi2 = 0; mi2 < 32; mi2++) { Map[mi1][mi2] = mi2; } @@ -730,120 +738,120 @@ if (MapInit == 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; +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, or WP */ - 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 (Fault) { /* Check MAP fault */ + Usermap = 0; /* YES: shutdown map */ + MapStat &= ~01; /* Disable MMPU */ + if (Fault & 0100000/*!!!*/) /* If it was validity, or WP */ + 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 (FPSR & 0xF8000000) { /* FPU Fault? */ - if (!(FPSR & 0x78000000)) { /* If error bit on ... */ - FPSR &= 0x00FFFFFF; /* ...but no error, clear it */ - } else { /* ELSE a real error: */ - FPSR |= 0x80000000; /* Turn error bit on */ - if (FPSR & 0x04000000) { /* Trap enabled ? */ - FPFault = FPSR; /* Save fault */ - FPSR &= 0xFBFFFFFF; /* Clear Trap Enable */ - } - } +if (FPSR & 0xF8000000) { /* FPU Fault? */ + if (!(FPSR & 0x78000000)) { /* If error bit on ... */ + FPSR &= 0x00FFFFFF; /* ...but no error, clear it */ + } else { /* ELSE a real error: */ + FPSR |= 0x80000000; /* Turn error bit on */ + if (FPSR & 0x04000000) { /* Trap enabled ? */ + FPFault = FPSR; /* Save fault */ + FPSR &= 0xFBFFFFFF; /* Clear Trap Enable */ + } + } } -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-1)) { - 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 (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-1)) { + 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 */ +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 (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; - } + if (PPC != -1) { /* Don't break on 1st instruction */ + printf("\n<>\n\r", PC, PPC); + reason = STOP_IBKPT; + break; + } } PPC = PC; @@ -863,17 +871,17 @@ if (Debug_Flags) { 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); + debpc = PC; + simeval[0] = GetMap(PC); + simeval[1] = GetMap(PC+1); } else { debpc = 0177777; - simeval[0] = XCT_inst; - simeval[1] = 0; - } + 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); + debion, debmap, debpc, AC[0], AC[1], AC[2], AC[3], debcar); fprint_sym (Trace, debpc, simeval, NULL, SWMASK('M')); fprintf(Trace, "\n"); } else { @@ -884,22 +892,22 @@ if (Debug_Flags) { if (Usermap == 2) debflags |= 0x08; if (Usermap == 3) debflags |= 0x10; if (Usermap == 4) debflags |= 0x20; - Debug_Entry(debpc, (int32)simeval[0], (int32)simeval[1], AC[0], AC[1], AC[2], AC[3], debflags); + Debug_Entry(debpc, (int32)simeval[0], (int32)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 */ +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 */ + 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 */ +int_req = int_req | INT_NO_ION_PENDING; /* clear ION delay */ sim_interval = sim_interval - 1; -t = IR >> 11; /* prepare to decode */ - +t = IR >> 11; /* prepare to decode */ + /* ---------------- BEGIN Eclipse modification --------------------- */ /* Eclipse instruction set. These instructions are checked for @@ -913,33 +921,33 @@ t = IR >> 11; /* prepare to decode */ the speed of the simulation. */ -if ((IR & 0100017) == 0100010) { /* This pattern for all */ - /* Eclipse instructions */ - +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) { + 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; + } 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; + 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 { @@ -952,7 +960,7 @@ if ((IR & 0100017) == 0100010) { /* This pattern for all */ /* Fixed-point arithmetic - loads & saves */ - if ((IR & 0162377) == 0122070) { /* ELDA: Extended LDA */ + if ((IR & 0162377) == 0122070) { /* ELDA: Extended LDA */ i = (IR >> 11) & 3; t = GetMap(PC); if (SingleCycle) Usermap = SingleCycle; @@ -966,7 +974,7 @@ if ((IR & 0100017) == 0100010) { /* This pattern for all */ PC = (PC + 1) & AMASK; continue; } - if ((IR & 0162377) == 0142070) { /* ESTA: Extended STA */ + if ((IR & 0162377) == 0142070) { /* ESTA: Extended STA */ i = (IR >> 11) & 3; t = GetMap(PC); if (SingleCycle) Usermap = SingleCycle; @@ -980,30 +988,30 @@ if ((IR & 0100017) == 0100010) { /* This pattern for all */ PC = (PC + 1) & AMASK; continue; } - if ((IR & 0103777) == 0100010) { /* ADI: Add Immediate */ + 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 */ + 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. */ + 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 */ + 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 */ + 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; @@ -1012,37 +1020,37 @@ if ((IR & 0100017) == 0100010) { /* This pattern for all */ /* Logical operations */ - if ((IR & 0163777) == 0143770) { /* ANDI: And Immediate */ + 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 */ + 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 */ + 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 */ + if ((IR & 0103777) == 0100410) { /* IOR: Inclusive Or */ AC[(IR >> 11) & 3] |= AC[(IR >> 13) & 3]; continue; } - if ((IR & 0103777) == 0100510) { /* XOR: Exclusive Or */ + 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 */ + 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 */ + if ((IR & 0103777) == 0101210) { /* LSH: Logical Shift */ register int16 sh; sh = AC[(IR >> 13) & 3] & 0377; i = (IR >> 11) & 3; @@ -1056,8 +1064,8 @@ if ((IR & 0100017) == 0100010) { /* This pattern for all */ AC[i] &= 0xffff; continue; } - if ((IR & 0103777) == 0101310) { /* DLSH: Double logical shift */ - register int16 sh; + 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; @@ -1077,21 +1085,21 @@ if ((IR & 0100017) == 0100010) { /* This pattern for all */ AC[j] = uAC0 & 0xffff; continue; } - if ((IR & 0103777) == 0101410) { /* HXL: Hex shift left */ + 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; + AC[i] &= 0xffff; continue; } - if ((IR & 0103777) == 0101510) { /* HXR: Hex shift right */ + 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; + AC[i] &= 0xffff; continue; } - if ((IR & 0103777) == 0101610) { /* DHXL: Double Hex shift left */ + if ((IR & 0103777) == 0101610) { /* DHXL: Double Hex shift left */ t = ((IR >> 13) & 3) + 1; i = (IR >> 11) & 3; j = i + 1; @@ -1103,7 +1111,7 @@ if ((IR & 0100017) == 0100010) { /* This pattern for all */ AC[j] = uAC0 & 0xffff; continue; } - if ((IR & 0103777) == 0101710) { /* DHXR: Double Hex shift right */ + if ((IR & 0103777) == 0101710) { /* DHXR: Double Hex shift right */ t = ((IR >> 13) & 3) + 1; i = (IR >> 11) & 3; j = i + 1; @@ -1115,19 +1123,18 @@ if ((IR & 0100017) == 0100010) { /* This pattern for all */ AC[j] = uAC0 & 0xffff; continue; } - /* Bit operations */ - if ((IR & 0103777) == 0102010) { /* BTO: Set bit to one */ - i = (IR >> 11) & 3; + 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; - if ((AC[j] + k) & 0100000) - t = 1; + if ((AC[j] + k) & 0100000) + t = 1; //AOS MA = indirect(AC[j] + k); - MA = (AC[j] + k) & AMASK; + MA = (AC[j] + k) & AMASK; } else { MA = (AC[i] >> 4) & AMASK; } @@ -1136,15 +1143,15 @@ if ((IR & 0100017) == 0100010) { /* This pattern for all */ PutMap(MA, t); continue; } - if ((IR & 0103777) == 0102110) { /* BTZ: Set bit to zero */ + 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; - if ((AC[j] + k) & 0100000) - t = 1; + if ((AC[j] + k) & 0100000) + t = 1; //AOS MA = indirect(AC[j] + k); - MA = (AC[j] + k) & AMASK; + MA = (AC[j] + k) & AMASK; } else { MA = (AC[j] >> 4) & AMASK; } @@ -1153,15 +1160,15 @@ if ((IR & 0100017) == 0100010) { /* This pattern for all */ PutMap(MA, t); continue; } - if ((IR & 0103777) == 0102210) { /* SZB: Skip on zero bit */ + 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; - if ((AC[j] + k) & 0100000) - t = 1; - MA = indirect(AC[j] + k); -// MA = (AC[j] + k) & AMASK; + if ((AC[j] + k) & 0100000) + t = 1; + MA = indirect(AC[j] + k); +// MA = (AC[j] + k) & AMASK; } else { MA = (AC[i] >> 4) & AMASK; } @@ -1169,15 +1176,15 @@ if ((IR & 0100017) == 0100010) { /* This pattern for all */ if (!(t & 0100000)) PC = (PC + 1) & AMASK; continue; } - if ((IR & 0103777) == 0102770) { /* SNB: Skip on non-zero bit */ + 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; - if ((AC[j] + k) & 0100000) - t = 1; - MA = indirect(AC[j] + k); -// MA = (AC[j] + k) & AMASK; + if ((AC[j] + k) & 0100000) + t = 1; + MA = indirect(AC[j] + k); +// MA = (AC[j] + k) & AMASK; } else { MA = (AC[j] >> 4) & AMASK; } @@ -1185,14 +1192,14 @@ if ((IR & 0100017) == 0100010) { /* This pattern for all */ if (t & 0100000) PC = (PC + 1) & AMASK; continue; } - if ((IR & 0103777) == 0102310) { /* SZBO: skip on zero bit & set to 1 */ + 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); -// MA = (AC[j] + k) & AMASK; + MA = indirect(AC[j] + k); +// MA = (AC[j] + k) & AMASK; } else { MA = (AC[j] >> 4) & AMASK; } @@ -1205,9 +1212,9 @@ if ((IR & 0100017) == 0100010) { /* This pattern for all */ PC = (PC + 1) & AMASK; continue; } - if ((IR & 0103777) == 0102410) { /* LOB: Locate lead bit */ + if ((IR & 0103777) == 0102410) { /* LOB: Locate lead bit */ register int32 a, r; - register int16 b, c = 0; + register int16 b; a = AC[(IR >> 13) & 3] & 0xffff; for (i = 0; i < 16; i++) { if ((a << i) & 0100000) break; @@ -1218,7 +1225,7 @@ if ((IR & 0100017) == 0100010) { /* This pattern for all */ AC[r] = b & 0177777; continue; } - if ((IR & 0103777) == 0102510) { /* LRB: Locate & reset lead bit */ + if ((IR & 0103777) == 0102510) { /* LRB: Locate & reset lead bit */ register int32 a, r; register int16 b; j = (IR >> 13) & 3; @@ -1234,7 +1241,7 @@ if ((IR & 0100017) == 0100010) { /* This pattern for all */ AC[j] &= 0xffff; continue; } - if ((IR & 0103777) == 0102610) { /* COB: Count bits */ + if ((IR & 0103777) == 0102610) { /* COB: Count bits */ register int32 a; register int16 b, c = 0; a = AC[(IR >> 13) & 3]; @@ -1248,34 +1255,33 @@ if ((IR & 0100017) == 0100010) { /* This pattern for all */ continue; } - /* Jump & similar operations */ - if ((IR & 0176377) == 0102070) { /* EJMP: Extended JMP */ + 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 */ + if ((IR & 0176377) == 0106070) { /* EJSR: Extended JMP to subr */ t = effective(PC, (IR >> 8) & 3, GetMap(PC)); - AC[3] = (PC + 1) & AMASK; + AC[3] = (PC + 1) & AMASK; PC = t & AMASK; continue; } - if ((IR & 0176377) == 0112070) { /* EISZ: Ext Inc & skip if 0 */ + 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 */ + 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 */ + 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; @@ -1283,7 +1289,7 @@ if ((IR & 0100017) == 0100010) { /* This pattern for all */ PC = (PC + 1) & AMASK; continue; } - if ((IR & 0103777) == 0101110) { /* SGE: Skip if ACS >= ACD */ + 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; @@ -1291,7 +1297,7 @@ if ((IR & 0100017) == 0100010) { /* This pattern for all */ PC = (PC + 1) & AMASK; continue; } - if ((IR & 0103777) == 0102370) { /* CLM: Compare to limits */ + if ((IR & 0103777) == 0102370) { /* CLM: Compare to limits */ register int32 s, d, MA; int16 H, L, ca; s = (IR >> 13) & 3; @@ -1310,16 +1316,16 @@ if ((IR & 0100017) == 0100010) { /* This pattern for all */ 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]; + 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; + if (IR == 0113710) { /* BAM: Block add & move */ + register int32 w; t = AC[1]; if (t < 1 || t > 0100000) continue; @@ -1340,13 +1346,13 @@ if ((IR & 0100017) == 0100010) { /* This pattern for all */ AC[3] = j & AMASK; continue; } - if (IR == 0133710) { /* BLM: Block move */ + if (IR == 0133710) { /* BLM: Block move */ t = AC[1]; if (t < 1 || t > 0100000) continue; i = indirect(AC[2]); j = indirect(AC[3]); - if (Fault) continue; + if (Fault) continue; while (t) { PutMap(j, GetMap(i)); if (Fault) break; @@ -1361,104 +1367,103 @@ if ((IR & 0100017) == 0100010) { /* This pattern for all */ 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) == 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)); + 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)); + 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)); - } + 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)); - } + 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 */ + 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; + 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]); @@ -1477,49 +1482,49 @@ if ((IR & 0100017) == 0100010) { /* This pattern for all */ PutMap(040, ((GetMap(040) + GetMap(savep)) & AMASK)); continue; } - if ((IR & 0163777) == 0103370) { /* MSP: Modify stack pointer */ + 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); + 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 */ + 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; - } + 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 */ + 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; } - j = GetMap(042); - t = GetMap(040); - if ((j < 0100000 && t < 0100000) && (t < 0400) && (t > 0)) { - pushrtn(PC); - PC = indirect(GetMap(043)); - PutMap(040, (GetMap(040) & 077777)); - PutMap(042, (GetMap(042) | 0100000)); - } + j = GetMap(042); + t = GetMap(040); + if ((j < 0100000 && t < 0100000) && (t < 0400) && (t > 0)) { + pushrtn(PC); + PC = indirect(GetMap(043)); + PutMap(040, (GetMap(040) & 077777)); + PutMap(042, (GetMap(042) | 0100000)); + } continue; } - if (IR == 0107710) { /* POPB: Pop block */ + if (IR == 0107710) { /* POPB: Pop block */ PC = GetMap(GetMap(040)) & AMASK; if (GetMap(GetMap(040)) & 0100000) C = 0200000; @@ -1535,23 +1540,23 @@ if ((IR & 0100017) == 0100010) { /* This pattern for all */ 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 (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 */ + if (IR == 0127710) { /* RTN: Return */ PutMap(040, GetMap(041)); PC = GetMap(GetMap(040)) & AMASK; - t = GetMap(040); - t = GetMap(t); + t = GetMap(040); + t = GetMap(t); if (t & 0100000) C = 0200000; else @@ -1567,19 +1572,19 @@ if ((IR & 0100017) == 0100010) { /* This pattern for all */ 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 (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 */ + if (IR == 0167710) { /* RSTR: Restore */ int32 SVPC; SVPC = PC; @@ -1609,10 +1614,10 @@ if ((IR & 0100017) == 0100010) { /* This pattern for all */ 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 (t < 0100000 && t < 0400) { + pushrtn(PC); + PC = indirect(GetMap(043)); + }*/ if (MapStat & 1) { Usermap = Enable; Inhibit = 0; @@ -1622,91 +1627,96 @@ if ((IR & 0100017) == 0100010) { /* This pattern for all */ /* Multiply / Divide */ - if (IR == 0143710) { /* MUL: Unsigned Multiply */ - uAC0 = (uint32) AC[0]; - uAC1 = (uint32) AC[1]; - uAC2 = (uint32) AC[2]; + if (IR == 0143710) { /* MUL: Unsigned Multiply */ + uAC0 = (uint32) AC[0]; + uAC1 = (uint32) AC[1]; + uAC2 = (uint32) AC[2]; - mddata = (uAC1 * uAC2) + uAC0; - AC[0] = (mddata >> 16) & 0177777; - AC[1] = mddata & 0177777; + 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]; + 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; + sddata = (sAC1 * sAC2) + sAC0; + AC[0] = (sddata >> 16) & 0177777; + AC[1] = sddata & 0177777; continue; } - if (IR == 0153710) { /* DIV: Unsigned Divide */ - uAC0 = (uint32) AC[0]; - uAC1 = (uint32) AC[1]; - uAC2 = (uint32) AC[2]; + if (IR == 0153710) { /* DIV: Unsigned Divide */ + uAC0 = (uint32) AC[0]; + uAC1 = (uint32) AC[1]; + uAC2 = (uint32) AC[2]; - if (uAC0 >= uAC2) C = 0200000; - else { C = 0; - mddata = (uAC0 << 16) | uAC1; - AC[1] = mddata / uAC2; - AC[0] = mddata % uAC2; - } + 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; + if (IR == 0157710) { /* DIVS: Signed Divide */ + if ((AC[0] == 0) || + ((AC[0] = 0100000) && (AC[1] == 0) && (AC[2] = 0177777))) + C = 0200000; + else { + 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 */ + 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]; + 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; - } + 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; - } + 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 */ + if ((IR & 0103777) == 0100210) { /* DAD: Decimal add */ i = (IR >> 13) & 3; j = (IR >> 11) & 3; t = (AC[i] & 017) + (AC[j] & 017); @@ -1721,7 +1731,7 @@ if ((IR & 0100017) == 0100010) { /* This pattern for all */ AC[j] = AC[j] | (t & 017); continue; } - if ((IR & 0103777) == 0100310) { /* DSB: Decimal subtract */ + if ((IR & 0103777) == 0100310) { /* DSB: Decimal subtract */ i = (IR >> 13) & 3; j = (IR >> 11) & 3; t = (AC[j] & 017) - (AC[i] & 017); @@ -1739,7 +1749,7 @@ if ((IR & 0100017) == 0100010) { /* This pattern for all */ /* Exotic, complex instructions */ - if ((IR & 0162377) == 0142170) { /* DSPA: Dispatch */ + if ((IR & 0162377) == 0142170) { /* DSPA: Dispatch */ register int32 d; int16 a, H, L; MA = effective(PC, (IR >> 8) & 3, GetMap(PC)); @@ -1755,17 +1765,17 @@ if ((IR & 0100017) == 0100010) { /* This pattern for all */ PC = (PC + 1) & AMASK; continue; } - PC = indirect(d) & AMASK; + PC = indirect(d) & AMASK; continue; } if (((IR & 0100077) == 0100030) || - ((IR & 0102077) == 0100070)) { /* XOP: Extended Operation */ + ((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 = GetMap(040) & AMASK; + for (i = 0; i <= 3; i++) { t++; PutMap(t, AC[i]); if (((IR >> 13) & 3) == i) sa = t; @@ -1778,24 +1788,24 @@ if ((IR & 0100017) == 0100010) { /* This pattern for all */ 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)); - } + 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 */ + if ((IR & 0103777) == 0103510) { /* SYC: System call */ register int32 j; DisMap = Usermap; Usermap = 0; - MapStat &= ~1; /* Disable MAP */ + MapStat &= ~1; /* Disable MAP */ i = (IR >> 13) & 3; j = (IR >> 11) & 3; if (i != 0 || j != 0) { - t = (GetMap(040) + 1) & AMASK; + t = (GetMap(040) + 1) & AMASK; PutMap(t, AC[0]); t++; PutMap(t, AC[1]); @@ -1811,32 +1821,32 @@ if ((IR & 0100017) == 0100010) { /* This pattern for all */ } 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)); - } + 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); + 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? */ + 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 */ + 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); + 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; } @@ -1846,7 +1856,7 @@ if ((IR & 0100017) == 0100010) { /* This pattern for all */ AC[0] = 0; AC[1] = t; AC[2] = i & AMASK; - MapStat &= ~02000; + MapStat &= ~02000; continue; } @@ -1854,25 +1864,25 @@ if ((IR & 0100017) == 0100010) { /* This pattern for all */ /* Character Instruction Set */ /****************************************************************/ - if ((IR & 0162377) == 0102170) { /* ELDB */ + if ((IR & 0162377) == 0102170) { /* ELDB */ t = Bytepointer(PC, (IR >> 8) & 3); - i = (IR >> 11) & 03; - MA = (t >> 1) & AMASK; - if (t & 01) { + i = (IR >> 11) & 03; + MA = (t >> 1) & AMASK; + if (t & 01) { AC[i] = GetMap(MA) & 0377; - } else { - AC[i] = (GetMap(MA) >> 8) & 0377; + } else { + AC[i] = (GetMap(MA) >> 8) & 0377; } PC = (PC + 1) & AMASK; continue; } - if ((IR & 0162377) == 0122170) { /* ESTB */ + 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; + i = (IR >> 11) & 03; + MA = (t >> 1) & AMASK; + j = GetMap(MA); + if (t & 01) { + j &= 0177400; j |= (AC[i] & 0377); PutMap(MA, j); } else { @@ -1884,31 +1894,31 @@ if ((IR & 0100017) == 0100010) { /* This pattern for all */ continue; } - if ((IR & 077) == 050) { /* All CIS end with 050 except ELDB/ESTB */ + 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 (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 (cmslen == 0) { - uAC2 = ' ' & 0377; /* Handle short source */ + uAC2 = ' ' & 0377; /* Handle short source */ } else { - if (cmsptr & 01) { - uAC2 = GetMap(MA) & 0377; /* Use uAC2 for temp */ - } else { - uAC2 = (GetMap(MA) >> 8) & 0377; - } - } - MA = (cmdptr >> 1) & AMASK; /* do an STB */ - j = GetMap(MA); - if (cmdptr & 01) { - j &= 0177400; + if (cmsptr & 01) { + uAC2 = GetMap(MA) & 0377; /* Use uAC2 for temp */ + } else { + uAC2 = (GetMap(MA) >> 8) & 0377; + } + } + MA = (cmdptr >> 1) & AMASK; /* do an STB */ + j = GetMap(MA); + if (cmdptr & 01) { + j &= 0177400; j |= (uAC2 & 0377); PutMap(MA, j); } else { @@ -1917,49 +1927,49 @@ if ((IR & 0100017) == 0100010) { /* This pattern for all */ 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; + 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; + } + + 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; + 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; @@ -1973,61 +1983,61 @@ if ((IR & 0100017) == 0100010) { /* This pattern for all */ 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; + 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 = GetMap(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; + } + if (IR == 0163650) { /* CTR Character translate */ + tabaddr = indirect(AC[0]); /* Get address of table */ + tabptr = GetMap(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 */ + cmptr = tabptr + j; /* Translate */ MA = (cmptr >> 1) & AMASK; - if (cmptr & 01) { - uAC2 = GetMap(MA) & 0377; - } else { - uAC2 = (GetMap(MA) >> 8) & 0377; + 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; + 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 { @@ -2035,14 +2045,14 @@ if ((IR & 0100017) == 0100010) { /* This pattern for all */ 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; + } 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 */ + cmptr = tabptr + j; /* Translate */ MA = (cmptr >> 1) & AMASK; if (cmptr & 01) { uAC3 = GetMap(MA) & 0377; @@ -2058,39 +2068,39 @@ if ((IR & 0100017) == 0100010) { /* This pattern for all */ 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 = GetMap(tabaddr + (uAC2 >> 4)); /* Test bit table */ - if (t << (uAC2 & 0x0F) & 0100000) /* quit if bit == 1 */ + cmsptr++; + cmdptr++; + cmslen--; + if (cmslen == 0) break; - MA = (cmdptr >> 1) & AMASK; /* do an STB */ - j = GetMap(MA); - if (cmdptr & 01) { - j &= 0177400; + } + 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 = GetMap(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 { @@ -2099,24 +2109,24 @@ if ((IR & 0100017) == 0100010) { /* This pattern for all */ 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; + 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 ** @@ -2124,2557 +2134,2557 @@ if ((IR & 0100017) == 0100010) { /* This pattern for all */ ** Instruction Set. ** ***********************************************************/ - if ((IR & 0163777) == 0103650) { /* LDI Load Integer */ - unimp(PC); + if ((IR & 0163777) == 0103650) { /* LDI Load Integer */ + unimp(PC); continue; - } - if ((IR & 0163777) == 0123650) { /* STI Store Integer */ - unimp(PC); + } + if ((IR & 0163777) == 0123650) { /* STI Store Integer */ + unimp(PC); continue; - } - if (IR == 0143650) { /* LDIX Load Int Extended */ - unimp(PC); + } + if (IR == 0143650) { /* LDIX Load Int Extended */ + unimp(PC); continue; - } - if (IR == 0143750) { /* STIX Store Int Extended */ - unimp(PC); + } + if (IR == 0143750) { /* STIX Store Int Extended */ + unimp(PC); continue; - } - if ((IR & 0163777) == 0143150) { /* FINT Integerize */ - unimp(PC); + } + if ((IR & 0163777) == 0143150) { /* FINT Integerize */ + unimp(PC); continue; - } - if (IR == 0177650) { /* LSN Load Sign */ - unimp(PC); + } + if (IR == 0177650) { /* LSN Load Sign */ + unimp(PC); continue; - } - if (IR == 0173650) { /* EDIT */ - unimp(PC); + } + if (IR == 0173650) { /* EDIT */ + unimp(PC); continue; - } + } } - /* FPU Instructions */ + /* FPU Instructions */ - if ((IR & 0163777) == 0123350) { /* FLST Load Status */ - if (!(fpu_unit.flags & UNIT_UP)) - continue; + if ((IR & 0163777) == 0123350) { /* FLST Load Status */ + if (!(fpu_unit.flags & UNIT_UP)) + continue; if (Debug_Flags == 1) { printf("\n<>\n"); reason = STOP_IBKPT; } - if (FPFault) { /* Fault from a previous inst? */ - FPFault = 0; - t = (GetMap(040) + 1) & AMASK; /* Yes: 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-1) & AMASK)); - if (C) PutMap(t, (GetMap(t) | 0100000)); - PutMap(040, t); - PC = indirect(GetMap(045)); /* JMP indirect to 45 */ - continue; - } - FPSR = 0; + if (FPFault) { /* Fault from a previous inst? */ + FPFault = 0; + t = (GetMap(040) + 1) & AMASK; /* Yes: 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-1) & AMASK)); + if (C) PutMap(t, (GetMap(t) | 0100000)); + PutMap(040, t); + PC = indirect(GetMap(045)); /* JMP indirect to 45 */ + continue; + } + FPSR = 0; MA = effective(PC, (IR >> 11) & 3, GetMap(PC)); - FPSR = (GetMap(MA) << 16); - FPSR |= (GetMap(MA + 1)); - FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */ - FPSR |= ((PC - 1) & AMASK); + FPSR = (GetMap(MA) << 16); + FPSR |= (GetMap(MA + 1)); + FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */ + FPSR |= ((PC - 1) & AMASK); PC = (PC + 1) & AMASK; continue; } - if ((IR & 0163777) == 0103350) { /* FSST Store Status */ - if (!(fpu_unit.flags & UNIT_UP)) - continue; + if ((IR & 0163777) == 0103350) { /* FSST Store Status */ + if (!(fpu_unit.flags & UNIT_UP)) + continue; if (Debug_Flags == 1) { printf("\n<>\n"); reason = STOP_IBKPT; } - if (FPFault) { /* Fault from a previous inst? */ - FPFault = 0; - t = (GetMap(040) + 1) & AMASK; /* Yes: 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-1) & AMASK)); - if (C) PutMap(t, (GetMap(t) | 0100000)); - PutMap(040, t); - PC = indirect(GetMap(045)); /* JMP indirect to 45 */ - continue; - } + if (FPFault) { /* Fault from a previous inst? */ + FPFault = 0; + t = (GetMap(040) + 1) & AMASK; /* Yes: 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-1) & AMASK)); + if (C) PutMap(t, (GetMap(t) | 0100000)); + PutMap(040, t); + PC = indirect(GetMap(045)); /* JMP indirect to 45 */ + continue; + } MA = effective(PC, (IR >> 11) & 3, GetMap(PC)); - FPSR &= 0xFFF0FFFF; /* Force FPU model */ - switch (model) { - case 200: - case 230: - case 300: - case 330: - FPSR |= 0x00000000; - break; - case 130: - FPSR |= 0x00010000; - break; - case 350: - case 600: - FPSR |= 0x00020000; - break; - case 250: - FPSR |= 0x00060000; - break; - default: - FPSR |= 0x000F0000; - break; - } - PutMap(MA, ((FPSR >> 16) & 0xFFFF)); - PutMap((MA + 1), FPSR & 0xFFFF); - FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */ - FPSR |= ((PC - 1) & AMASK); + FPSR &= 0xFFF0FFFF; /* Force FPU model */ + switch (model) { + case 200: + case 230: + case 300: + case 330: + FPSR |= 0x00000000; + break; + case 130: + FPSR |= 0x00010000; + break; + case 350: + case 600: + FPSR |= 0x00020000; + break; + case 250: + FPSR |= 0x00060000; + break; + default: + FPSR |= 0x000F0000; + break; + } + PutMap(MA, ((FPSR >> 16) & 0xFFFF)); + PutMap((MA + 1), FPSR & 0xFFFF); + FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */ + FPSR |= ((PC - 1) & AMASK); PC = (PC + 1) & AMASK; continue; } - if ((IR & 0103777) == 0102050) { /* FLDS Load FP single */ - if (!(fpu_unit.flags & UNIT_UP)) - continue; + if ((IR & 0103777) == 0102050) { /* FLDS Load FP single */ + if (!(fpu_unit.flags & UNIT_UP)) + continue; if (Debug_Flags == 1) { printf("\n<>\n"); reason = STOP_IBKPT; } - if (FPFault) { /* Fault from a previous inst? */ - FPFault = 0; - t = (GetMap(040) + 1) & AMASK; /* Yes: 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-1) & AMASK)); - if (C) PutMap(t, (GetMap(t) | 0100000)); - PutMap(040, t); - PC = indirect(GetMap(045)); /* JMP indirect to 45 */ - continue; - } - i = (IR >> 11) & 0x03; - FPAC[i] = 0; + if (FPFault) { /* Fault from a previous inst? */ + FPFault = 0; + t = (GetMap(040) + 1) & AMASK; /* Yes: 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-1) & AMASK)); + if (C) PutMap(t, (GetMap(t) | 0100000)); + PutMap(040, t); + PC = indirect(GetMap(045)); /* JMP indirect to 45 */ + continue; + } + i = (IR >> 11) & 0x03; + FPAC[i] = 0; MA = effective(PC, (IR >> 13) & 3, GetMap(PC)); - t = GetMap(MA) & 0xffff; - FPAC[i] = (t_int64) t << 48; - t = GetMap(MA+1) & 0xffff; - FPAC[i] |= (t_int64) t << 32; - if ((FPAC[i] & 0x00ffffffffffffff) == 0) - FPAC[i] = 0; - FPSR &= 0xFCFFFFFF; - if (FPAC[i] == 0) - FPSR |= 0x02000000; - if (FPAC[i] & 0x8000000000000000) - FPSR |= 0x01000000; - FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */ - FPSR |= ((PC - 1) & AMASK); + t = GetMap(MA) & 0xffff; + FPAC[i] = (t_int64) t << 48; + t = GetMap(MA+1) & 0xffff; + FPAC[i] |= (t_int64) t << 32; + if ((FPAC[i] & 0x00ffffffffffffff) == 0) + FPAC[i] = 0; + FPSR &= 0xFCFFFFFF; + if (FPAC[i] == 0) + FPSR |= 0x02000000; + if (FPAC[i] & 0x8000000000000000) + FPSR |= 0x01000000; + FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */ + FPSR |= ((PC - 1) & AMASK); PC = (PC + 1) & AMASK; continue; } - if ((IR & 0103777) == 0102150) { /* FLDD Load FP double */ - if (!(fpu_unit.flags & UNIT_UP)) - continue; + if ((IR & 0103777) == 0102150) { /* FLDD Load FP double */ + if (!(fpu_unit.flags & UNIT_UP)) + continue; if (Debug_Flags == 1) { printf("\n<>\n"); reason = STOP_IBKPT; } - if (FPFault) { /* Fault from a previous inst? */ - FPFault = 0; - t = (GetMap(040) + 1) & AMASK; /* Yes: 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-1) & AMASK)); - if (C) PutMap(t, (GetMap(t) | 0100000)); - PutMap(040, t); - PC = indirect(GetMap(045)); /* JMP indirect to 45 */ - continue; - } - i = (IR >> 11) & 0x03; - FPAC[i] = 0; + if (FPFault) { /* Fault from a previous inst? */ + FPFault = 0; + t = (GetMap(040) + 1) & AMASK; /* Yes: 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-1) & AMASK)); + if (C) PutMap(t, (GetMap(t) | 0100000)); + PutMap(040, t); + PC = indirect(GetMap(045)); /* JMP indirect to 45 */ + continue; + } + i = (IR >> 11) & 0x03; + FPAC[i] = 0; MA = effective(PC, (IR >> 13) & 3, GetMap(PC)); - t = GetMap(MA) & 0xffff; - FPAC[i] = (t_int64) t << 48; - t = GetMap(MA+1) & 0xffff; - FPAC[i] |= (t_int64) t << 32; - t = GetMap(MA+2) & 0xffff; - FPAC[i] |= (t_int64) t << 16; - t = GetMap(MA+3) & 0xffff; - FPAC[i] |= (t_int64) t; - if ((FPAC[i] & 0x00ffffffffffffff) == 0) - FPAC[i] = 0; - FPSR &= 0xFCFFFFFF; - if (FPAC[i] == 0) - FPSR |= 0x02000000; - if (FPAC[i] & 0x8000000000000000) - FPSR |= 0x01000000; - FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */ - FPSR |= ((PC - 1) & AMASK); + t = GetMap(MA) & 0xffff; + FPAC[i] = (t_int64) t << 48; + t = GetMap(MA+1) & 0xffff; + FPAC[i] |= (t_int64) t << 32; + t = GetMap(MA+2) & 0xffff; + FPAC[i] |= (t_int64) t << 16; + t = GetMap(MA+3) & 0xffff; + FPAC[i] |= (t_int64) t; + if ((FPAC[i] & 0x00ffffffffffffff) == 0) + FPAC[i] = 0; + FPSR &= 0xFCFFFFFF; + if (FPAC[i] == 0) + FPSR |= 0x02000000; + if (FPAC[i] & 0x8000000000000000) + FPSR |= 0x01000000; + FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */ + FPSR |= ((PC - 1) & AMASK); PC = (PC + 1) & AMASK; continue; } - if ((IR & 0103777) == 0102250) { /* FSTS Store FP single */ - if (!(fpu_unit.flags & UNIT_UP)) - continue; + if ((IR & 0103777) == 0102250) { /* FSTS Store FP single */ + if (!(fpu_unit.flags & UNIT_UP)) + continue; if (Debug_Flags == 1) { printf("\n<>\n"); reason = STOP_IBKPT; } - if (FPFault) { /* Fault from a previous inst? */ - FPFault = 0; - t = (GetMap(040) + 1) & AMASK; /* Yes: 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-1) & AMASK)); - if (C) PutMap(t, (GetMap(t) | 0100000)); - PutMap(040, t); - PC = indirect(GetMap(045)); /* JMP indirect to 45 */ - continue; - } - i = (IR >> 11) & 0x03; + if (FPFault) { /* Fault from a previous inst? */ + FPFault = 0; + t = (GetMap(040) + 1) & AMASK; /* Yes: 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-1) & AMASK)); + if (C) PutMap(t, (GetMap(t) | 0100000)); + PutMap(040, t); + PC = indirect(GetMap(045)); /* JMP indirect to 45 */ + continue; + } + i = (IR >> 11) & 0x03; MA = effective(PC, (IR >> 13) & 3, GetMap(PC)); - PutMap(MA, (int32)(FPAC[i] >> 48) & 0xffff); - PutMap(MA+1, (int32)(FPAC[i] >> 32) & 0xffff); - FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */ - FPSR |= ((PC - 1) & AMASK); + PutMap(MA, (int32)(FPAC[i] >> 48) & 0xffff); + PutMap(MA+1, (int32)(FPAC[i] >> 32) & 0xffff); + FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */ + FPSR |= ((PC - 1) & AMASK); PC = (PC + 1) & AMASK; continue; } - if ((IR & 0103777) == 0102350) { /* FSTD Store FP double */ - if (!(fpu_unit.flags & UNIT_UP)) - continue; + if ((IR & 0103777) == 0102350) { /* FSTD Store FP double */ + if (!(fpu_unit.flags & UNIT_UP)) + continue; if (Debug_Flags == 1) { printf("\n<>\n"); reason = STOP_IBKPT; } - if (FPFault) { /* Fault from a previous inst? */ - FPFault = 0; - t = (GetMap(040) + 1) & AMASK; /* Yes: 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-1) & AMASK)); - if (C) PutMap(t, (GetMap(t) | 0100000)); - PutMap(040, t); - PC = indirect(GetMap(045)); /* JMP indirect to 45 */ - continue; - } - i = (IR >> 11) & 0x03; + if (FPFault) { /* Fault from a previous inst? */ + FPFault = 0; + t = (GetMap(040) + 1) & AMASK; /* Yes: 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-1) & AMASK)); + if (C) PutMap(t, (GetMap(t) | 0100000)); + PutMap(040, t); + PC = indirect(GetMap(045)); /* JMP indirect to 45 */ + continue; + } + i = (IR >> 11) & 0x03; MA = effective(PC, (IR >> 13) & 3, GetMap(PC)); - PutMap(MA, (int32)(FPAC[i] >> 48) & 0xffff); - PutMap(MA+1, (int32)(FPAC[i] >> 32) & 0xffff); - PutMap(MA+2, (int32)(FPAC[i] >> 16) & 0xffff); - PutMap(MA+3, (int32)(FPAC[i] & 0xffff)); - FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */ - FPSR |= ((PC - 1) & AMASK); + PutMap(MA, (int32)(FPAC[i] >> 48) & 0xffff); + PutMap(MA+1, (int32)(FPAC[i] >> 32) & 0xffff); + PutMap(MA+2, (int32)(FPAC[i] >> 16) & 0xffff); + PutMap(MA+3, (int32)(FPAC[i] & 0xffff)); + FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */ + FPSR |= ((PC - 1) & AMASK); PC = (PC + 1) & AMASK; continue; } - if ((IR & 0103777) == 0103550) { /* FMOV Move FP */ - if (!(fpu_unit.flags & UNIT_UP)) - continue; + if ((IR & 0103777) == 0103550) { /* FMOV Move FP */ + if (!(fpu_unit.flags & UNIT_UP)) + continue; if (Debug_Flags == 1) { printf("\n<>\n"); reason = STOP_IBKPT; - continue; + continue; } - if (FPFault) { /* Fault from a previous inst? */ - FPFault = 0; - t = (GetMap(040) + 1) & AMASK; /* Yes: 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-1) & AMASK)); - if (C) PutMap(t, (GetMap(t) | 0100000)); - PutMap(040, t); - PC = indirect(GetMap(045)); /* JMP indirect to 45 */ - continue; - } + if (FPFault) { /* Fault from a previous inst? */ + FPFault = 0; + t = (GetMap(040) + 1) & AMASK; /* Yes: 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-1) & AMASK)); + if (C) PutMap(t, (GetMap(t) | 0100000)); + PutMap(040, t); + PC = indirect(GetMap(045)); /* JMP indirect to 45 */ + continue; + } i = (IR >> 13) & 3; j = (IR >> 11) & 3; - FPAC[j] = FPAC[i]; - if ((FPAC[j] & 0x00ffffffffffffff) == 0) - FPAC[j] = 0; - FPSR &= 0xFCFFFFFF; - if (FPAC[j] == 0) - FPSR |= 0x02000000; - if (FPAC[j] & 0x8000000000000000) - FPSR |= 0x01000000; - FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */ - FPSR |= ((PC - 1) & AMASK); + FPAC[j] = FPAC[i]; + if ((FPAC[j] & 0x00ffffffffffffff) == 0) + FPAC[j] = 0; + FPSR &= 0xFCFFFFFF; + if (FPAC[j] == 0) + FPSR |= 0x02000000; + if (FPAC[j] & 0x8000000000000000) + FPSR |= 0x01000000; + FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */ + FPSR |= ((PC - 1) & AMASK); continue; } - if (IR == 0143350) { /* FTE Trap Enable */ - if (!(fpu_unit.flags & UNIT_UP)) - continue; + if (IR == 0143350) { /* FTE Trap Enable */ + if (!(fpu_unit.flags & UNIT_UP)) + continue; if (Debug_Flags == 2) { printf("\n<>\n"); reason = STOP_IBKPT; } - if (FPFault) { /* Fault from a previous inst? */ - FPFault = 0; - t = (GetMap(040) + 1) & AMASK; /* Yes: 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-1) & AMASK)); - if (C) PutMap(t, (GetMap(t) | 0100000)); - PutMap(040, t); - PC = indirect(GetMap(045)); /* JMP indirect to 45 */ - continue; - } - FPSR |= 0x04000000; - FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */ - FPSR |= ((PC - 1) & AMASK); + if (FPFault) { /* Fault from a previous inst? */ + FPFault = 0; + t = (GetMap(040) + 1) & AMASK; /* Yes: 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-1) & AMASK)); + if (C) PutMap(t, (GetMap(t) | 0100000)); + PutMap(040, t); + PC = indirect(GetMap(045)); /* JMP indirect to 45 */ + continue; + } + FPSR |= 0x04000000; + FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */ + FPSR |= ((PC - 1) & AMASK); continue; } - if (IR == 0147350) { /* FTD Trap Disable */ - if (!(fpu_unit.flags & UNIT_UP)) - continue; + if (IR == 0147350) { /* FTD Trap Disable */ + if (!(fpu_unit.flags & UNIT_UP)) + continue; if (Debug_Flags == 1) { printf("\n<>\n"); reason = STOP_IBKPT; } - if (FPFault) { /* Fault from a previous inst? */ - FPFault = 0; - t = (GetMap(040) + 1) & AMASK; /* Yes: 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-1) & AMASK)); - if (C) PutMap(t, (GetMap(t) | 0100000)); - PutMap(040, t); - PC = indirect(GetMap(045)); /* JMP indirect to 45 */ - continue; - } - FPSR &= 0xFBFFFFFF; - FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */ - FPSR |= ((PC - 1) & AMASK); + if (FPFault) { /* Fault from a previous inst? */ + FPFault = 0; + t = (GetMap(040) + 1) & AMASK; /* Yes: 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-1) & AMASK)); + if (C) PutMap(t, (GetMap(t) | 0100000)); + PutMap(040, t); + PC = indirect(GetMap(045)); /* JMP indirect to 45 */ + continue; + } + FPSR &= 0xFBFFFFFF; + FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */ + FPSR |= ((PC - 1) & AMASK); continue; } - if ((IR & 0103777) == 0102450) { /* FLAS Float from AC */ - if (!(fpu_unit.flags & UNIT_UP)) - continue; + if ((IR & 0103777) == 0102450) { /* FLAS Float from AC */ + if (!(fpu_unit.flags & UNIT_UP)) + continue; if (Debug_Flags == 1) { printf("\n<>\n"); reason = STOP_IBKPT; } - if (FPFault) { /* Fault from a previous inst? */ - FPFault = 0; - t = (GetMap(040) + 1) & AMASK; /* Yes: 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-1) & AMASK)); - if (C) PutMap(t, (GetMap(t) | 0100000)); - PutMap(040, t); - PC = indirect(GetMap(045)); /* JMP indirect to 45 */ - continue; - } - i = (IR >> 13) & 3; - j = (IR >> 11) & 3; - if (AC[i] == 0) { - FPAC[j] = 0; - FPSR |= 0x02000000; - continue; - } - fpnum = (t_int64)(AC[i] & 077777) << 32; - if (AC[i] & 0x8000) - fpnum = 0 - fpnum; - expon = 70; - while (1) { - if (fpnum & 0x00FF000000000000) - break; - if (expon < 64) - break; - fpnum = fpnum << 4; - expon--; - } - FPAC[j] = 0; - FPAC[j] = fpnum & 0x00ffffffffffffff; - FPAC[j] |= (expon << 56) & 0x7f00000000000000; - if (AC[i] & 0x8000) - FPAC[j] |= 0x8000000000000000; - if ((FPAC[j] & 0x00ffffffffffffff) == 0) - FPAC[j] = 0; - FPSR &= 0xFCFFFFFF; - if (FPAC[j] == 0) - FPSR |= 0x02000000; - if (FPAC[j] & 0x8000000000000000) - FPSR |= 0x01000000; - FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */ - FPSR |= ((PC - 1) & AMASK); + if (FPFault) { /* Fault from a previous inst? */ + FPFault = 0; + t = (GetMap(040) + 1) & AMASK; /* Yes: 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-1) & AMASK)); + if (C) PutMap(t, (GetMap(t) | 0100000)); + PutMap(040, t); + PC = indirect(GetMap(045)); /* JMP indirect to 45 */ + continue; + } + i = (IR >> 13) & 3; + j = (IR >> 11) & 3; + if (AC[i] == 0) { + FPAC[j] = 0; + FPSR |= 0x02000000; + continue; + } + fpnum = (t_int64)(AC[i] & 077777) << 32; + if (AC[i] & 0x8000) + fpnum = 0 - fpnum; + expon = 70; + while (1) { + if (fpnum & 0x00FF000000000000) + break; + if (expon < 64) + break; + fpnum = fpnum << 4; + expon--; + } + FPAC[j] = 0; + FPAC[j] = fpnum & 0x00ffffffffffffff; + FPAC[j] |= (expon << 56) & 0x7f00000000000000; + if (AC[i] & 0x8000) + FPAC[j] |= 0x8000000000000000; + if ((FPAC[j] & 0x00ffffffffffffff) == 0) + FPAC[j] = 0; + FPSR &= 0xFCFFFFFF; + if (FPAC[j] == 0) + FPSR |= 0x02000000; + if (FPAC[j] & 0x8000000000000000) + FPSR |= 0x01000000; + FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */ + FPSR |= ((PC - 1) & AMASK); continue; } - if ((IR & 0103777) == 0102550) { /* FLMD Float from memory */ - if (!(fpu_unit.flags & UNIT_UP)) - continue; + if ((IR & 0103777) == 0102550) { /* FLMD Float from memory */ + if (!(fpu_unit.flags & UNIT_UP)) + continue; if (Debug_Flags == 1) { printf("\n<>\n"); reason = STOP_IBKPT; } - if (FPFault) { /* Fault from a previous inst? */ - FPFault = 0; - t = (GetMap(040) + 1) & AMASK; /* Yes: 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-1) & AMASK)); - if (C) PutMap(t, (GetMap(t) | 0100000)); - PutMap(040, t); - PC = indirect(GetMap(045)); /* JMP indirect to 45 */ - continue; - } - i = (IR >> 13) & 3; - j = (IR >> 11) & 3; + if (FPFault) { /* Fault from a previous inst? */ + FPFault = 0; + t = (GetMap(040) + 1) & AMASK; /* Yes: 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-1) & AMASK)); + if (C) PutMap(t, (GetMap(t) | 0100000)); + PutMap(040, t); + PC = indirect(GetMap(045)); /* JMP indirect to 45 */ + continue; + } + i = (IR >> 13) & 3; + j = (IR >> 11) & 3; MA = effective(PC, (IR >> 13) & 3, GetMap(PC)); PC = (PC + 1) & AMASK; - fpnum32 = 0; - fpnum32 = (GetMap(MA) << 16); - fpnum32 |= (GetMap(MA + 1)); - if (fpnum32 == 0) { - FPAC[j] = 0; - FPSR |= 0x02000000; - continue; - } - fpnum = (t_int64)(fpnum32 & 0xffffffff) << 32; - if (fpnum32 < 0) - fpnum = (0 - fpnum); - expon = 70; - while (1) { - if (fpnum & 0x00F0000000000000) - break; - if (expon < 64) - break; - fpnum = fpnum << 4; - expon--; - } - FPAC[j] = 0; - FPAC[j] = fpnum & 0x00ffffffffffffff; - FPAC[j] |= (expon << 56) & 0x7f00000000000000; - if (fpnum32 < 0) - FPAC[j] |= 0x8000000000000000; - if ((FPAC[j] & 0x00ffffffffffffff) == 0) - FPAC[j] = 0; - FPSR &= 0xFCFFFFFF; - if (FPAC[j] == 0) - FPSR |= 0x02000000; - if (FPAC[j] & 0x8000000000000000) - FPSR |= 0x01000000; - FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */ - FPSR |= ((PC - 1) & AMASK); + fpnum32 = 0; + fpnum32 = (GetMap(MA) << 16); + fpnum32 |= (GetMap(MA + 1)); + if (fpnum32 == 0) { + FPAC[j] = 0; + FPSR |= 0x02000000; + continue; + } + fpnum = (t_int64)(fpnum32 & 0xffffffff) << 32; + if (fpnum32 < 0) + fpnum = (0 - fpnum); + expon = 70; + while (1) { + if (fpnum & 0x00F0000000000000) + break; + if (expon < 64) + break; + fpnum = fpnum << 4; + expon--; + } + FPAC[j] = 0; + FPAC[j] = fpnum & 0x00ffffffffffffff; + FPAC[j] |= (expon << 56) & 0x7f00000000000000; + if (fpnum32 < 0) + FPAC[j] |= 0x8000000000000000; + if ((FPAC[j] & 0x00ffffffffffffff) == 0) + FPAC[j] = 0; + FPSR &= 0xFCFFFFFF; + if (FPAC[j] == 0) + FPSR |= 0x02000000; + if (FPAC[j] & 0x8000000000000000) + FPSR |= 0x01000000; + FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */ + FPSR |= ((PC - 1) & AMASK); continue; } - if ((IR & 0103777) == 0102650) { /* FFAS Fix to AC */ - if (!(fpu_unit.flags & UNIT_UP)) - continue; + if ((IR & 0103777) == 0102650) { /* FFAS Fix to AC */ + if (!(fpu_unit.flags & UNIT_UP)) + continue; if (Debug_Flags == 1) { printf("\n<>\n"); reason = STOP_IBKPT; } - if (FPFault) { /* Fault from a previous inst? */ - FPFault = 0; - t = (GetMap(040) + 1) & AMASK; /* Yes: 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-1) & AMASK)); - if (C) PutMap(t, (GetMap(t) | 0100000)); - PutMap(040, t); - PC = indirect(GetMap(045)); /* JMP indirect to 45 */ - continue; - } - i = (IR >> 13) & 3; - j = (IR >> 11) & 3; - tac = AC[0]; + if (FPFault) { /* Fault from a previous inst? */ + FPFault = 0; + t = (GetMap(040) + 1) & AMASK; /* Yes: 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-1) & AMASK)); + if (C) PutMap(t, (GetMap(t) | 0100000)); + PutMap(040, t); + PC = indirect(GetMap(045)); /* JMP indirect to 45 */ + continue; + } + i = (IR >> 13) & 3; + j = (IR >> 11) & 3; + tac = AC[0]; - t = 0; + t = 0; - FPSR &= 0xFCFFFFFF; /* Z+N bits off */ + FPSR &= 0xFCFFFFFF; /* Z+N bits off */ - /* Get register content */ - get_lf(&dfl, &FPAC[j]); + /* Get register content */ + get_lf(&dfl, &FPAC[j]); - if (dfl.long_fract) { - /* not zero */ - normal_lf(&dfl); + if (dfl.long_fract) { + /* not zero */ + normal_lf(&dfl); - if (dfl.expo > 72) { - /* ERROR: exceeds range by exponent */ - FPSR |= 0x08000000; /* MOF bit on */ - dfl.long_fract &= 0x7FFFFFFF; - } - if (dfl.expo > 64) { - /* to be right shifted and to be rounded */ - shift = ((78 - dfl.expo) * 4); - lsfract = dfl.long_fract << (64 - shift); - dfl.long_fract >>= shift; - if (dfl.expo == 72) { - if (dfl.sign) { - /* negative */ - if (dfl.long_fract > 0x80000000) { - /* ERROR: exceeds range by value */ - FPSR |= 0x08000000; /* MOF bit on */ - dfl.long_fract &= 0x7FFFFFFF; - } - } else { - /* positive */ - if (dfl.long_fract > 0x7FFFFFFF) { - /* ERROR: exceeds range by value */ - FPSR |= 0x08000000; /* MOF bit on */ - dfl.long_fract &= 0x7FFFFFFF; - } - } - } - } else if (dfl.expo == 64) { - /* to be rounded */ - lsfract = dfl.long_fract << 8; - dfl.long_fract = 0; - } else { - /* fl.expo < 64 */ - dfl.long_fract = 0; - if (((m3 == 6) - && (dfl.sign == 0)) - || ((m3 == 7) - && (dfl.sign == 1))) { - dfl.long_fract++; - } - } - if (dfl.sign) { - /* negative */ - //FPSR |= 0x01000000; /* N bit on */ - k = -(int32)dfl.long_fract & 0xFFFFFFFF; - } else { - /* positive */ - k = (int32)dfl.long_fract & 0xFFFFFFFF; - } - } else { - /* zero */ - k = 0; - //FPSR |= 0x02000000; /* Z bit on */ - } - AC[i] = k & 0x7FFF; - if (k > 32767 || k < -32768) - FPSR |= 0x08000000; /* MOF bit on */ - if (k < 0) AC[i] |= 0x8000; - FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */ - FPSR |= ((PC - 1) & AMASK); - if (FPSR & 0x08000000) AC[i] = tac; /* shifted to zero, restore saved AC */ - continue; + if (dfl.expo > 72) { + /* ERROR: exceeds range by exponent */ + FPSR |= 0x08000000; /* MOF bit on */ + dfl.long_fract &= 0x7FFFFFFF; + } + if (dfl.expo > 64) { + /* to be right shifted and to be rounded */ + shift = ((78 - dfl.expo) * 4); + lsfract = dfl.long_fract << (64 - shift); + dfl.long_fract >>= shift; + if (dfl.expo == 72) { + if (dfl.sign) { + /* negative */ + if (dfl.long_fract > 0x80000000) { + /* ERROR: exceeds range by value */ + FPSR |= 0x08000000; /* MOF bit on */ + dfl.long_fract &= 0x7FFFFFFF; + } + } else { + /* positive */ + if (dfl.long_fract > 0x7FFFFFFF) { + /* ERROR: exceeds range by value */ + FPSR |= 0x08000000; /* MOF bit on */ + dfl.long_fract &= 0x7FFFFFFF; + } + } + } + } else if (dfl.expo == 64) { + /* to be rounded */ + lsfract = dfl.long_fract << 8; + dfl.long_fract = 0; + } else { + /* fl.expo < 64 */ + dfl.long_fract = 0; + if (((m3 == 6) + && (dfl.sign == 0)) + || ((m3 == 7) + && (dfl.sign == 1))) { + dfl.long_fract++; + } + } + if (dfl.sign) { + /* negative */ + //FPSR |= 0x01000000; /* N bit on */ + k = -(int32)dfl.long_fract & 0xFFFFFFFF; + } else { + /* positive */ + k = (int32)dfl.long_fract & 0xFFFFFFFF; + } + } else { + /* zero */ + k = 0; + //FPSR |= 0x02000000; /* Z bit on */ + } + AC[i] = k & 0x7FFF; + if (k > 32767 || k < -32768) + FPSR |= 0x08000000; /* MOF bit on */ + if (k < 0) AC[i] |= 0x8000; + FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */ + FPSR |= ((PC - 1) & AMASK); + if (FPSR & 0x08000000) AC[i] = tac; /* shifted to zero, restore saved AC */ + continue; } - if ((IR & 0103777) == 0102750) { /* FFMD Fix to Memory */ - if (!(fpu_unit.flags & UNIT_UP)) - continue; + if ((IR & 0103777) == 0102750) { /* FFMD Fix to Memory */ + if (!(fpu_unit.flags & UNIT_UP)) + continue; if (Debug_Flags == 1) { printf("\n<>\n"); reason = STOP_IBKPT; } - if (FPFault) { /* Fault from a previous inst? */ - FPFault = 0; - t = (GetMap(040) + 1) & AMASK; /* Yes: 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-1) & AMASK)); - if (C) PutMap(t, (GetMap(t) | 0100000)); - PutMap(040, t); - PC = indirect(GetMap(045)); /* JMP indirect to 45 */ - continue; - } - j = (IR >> 11) & 3; - MA = effective(PC, (IR >> 13) & 3, GetMap(PC)); - PC = (PC + 1) & AMASK; + if (FPFault) { /* Fault from a previous inst? */ + FPFault = 0; + t = (GetMap(040) + 1) & AMASK; /* Yes: 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-1) & AMASK)); + if (C) PutMap(t, (GetMap(t) | 0100000)); + PutMap(040, t); + PC = indirect(GetMap(045)); /* JMP indirect to 45 */ + continue; + } + j = (IR >> 11) & 3; + MA = effective(PC, (IR >> 13) & 3, GetMap(PC)); + PC = (PC + 1) & AMASK; - t = 0; - if (FPAC[j] == 0x521E290F94874A43) /* Wrote 0000 0000 expected 4A43 0000 ... MOF bit is on! What is the default??? */ - t = 1; - if (FPAC[j] == 0x53F129F814FC8A7E) /* Wrote 0000 0000 expected 27E0 0000 ... MOF bit is on! What is the default??? */ - t = 2; - if (FPAC[j] == 0xD01B680DB406DA03) /* Wrote 0000 0000 expected F925 FD00 ... MOF bit is on! What is the default??? */ - t = 3; + t = 0; + if (FPAC[j] == 0x521E290F94874A43) /* Wrote 0000 0000 expected 4A43 0000 ... MOF bit is on! What is the default??? */ + t = 1; + if (FPAC[j] == 0x53F129F814FC8A7E) /* Wrote 0000 0000 expected 27E0 0000 ... MOF bit is on! What is the default??? */ + t = 2; + if (FPAC[j] == 0xD01B680DB406DA03) /* Wrote 0000 0000 expected F925 FD00 ... MOF bit is on! What is the default??? */ + t = 3; - FPSR &= 0xFCFFFFFF; /* Z+N bits off */ + FPSR &= 0xFCFFFFFF; /* Z+N bits off */ - /* Get register content */ - get_lf(&dfl, &FPAC[j]); + /* Get register content */ + get_lf(&dfl, &FPAC[j]); - if (dfl.long_fract) { - /* not zero */ - normal_lf(&dfl); + if (dfl.long_fract) { + /* not zero */ + normal_lf(&dfl); - if (dfl.expo > 72) { - /* ERROR: exceeds range by exponent */ - FPSR |= 0x08000000; /* MOF bit on */ - //dfl.long_fract &= 0x7FFFFFFF; - } - if (dfl.expo > 64) { - /* to be right shifted and to be rounded */ - shift = ((78 - dfl.expo) * 4); - lsfract = dfl.long_fract << (64 - shift); - dfl.long_fract >>= shift; - if (dfl.expo == 72) { - if (dfl.sign) { - /* negative */ - if (dfl.long_fract > 0x80000000) { - /* ERROR: exceeds range by value */ - FPSR |= 0x08000000; /* MOF bit on */ - dfl.long_fract &= 0x7FFFFFFF; - } - } else { - /* positive */ - if (dfl.long_fract > 0x7FFFFFFF) { - /* ERROR: exceeds range by value */ - FPSR |= 0x08000000; /* MOF bit on */ - dfl.long_fract &= 0x7FFFFFFF; - } - } - } - } else if (dfl.expo == 64) { - /* to be rounded */ - lsfract = dfl.long_fract << 8; - dfl.long_fract = 0; - } else { - /* fl.expo < 64 */ - dfl.long_fract = 0; - if (((m3 == 6) - && (dfl.sign == 0)) - || ((m3 == 7) - && (dfl.sign == 1))) { - dfl.long_fract++; - } - } - if (dfl.sign) { - /* negative */ - //FPSR |= 0x01000000; /* N bit on */ - i = -(int32)dfl.long_fract & 0xFFFFFFFF; - } else { - /* positive */ - i = (int32)dfl.long_fract & 0xFFFFFFFF; - } - } else { - /* zero */ - i = 0; - //FPSR |= 0x02000000; /* Z bit on */ - } + if (dfl.expo > 72) { + /* ERROR: exceeds range by exponent */ + FPSR |= 0x08000000; /* MOF bit on */ + //dfl.long_fract &= 0x7FFFFFFF; + } + if (dfl.expo > 64) { + /* to be right shifted and to be rounded */ + shift = ((78 - dfl.expo) * 4); + lsfract = dfl.long_fract << (64 - shift); + dfl.long_fract >>= shift; + if (dfl.expo == 72) { + if (dfl.sign) { + /* negative */ + if (dfl.long_fract > 0x80000000) { + /* ERROR: exceeds range by value */ + FPSR |= 0x08000000; /* MOF bit on */ + dfl.long_fract &= 0x7FFFFFFF; + } + } else { + /* positive */ + if (dfl.long_fract > 0x7FFFFFFF) { + /* ERROR: exceeds range by value */ + FPSR |= 0x08000000; /* MOF bit on */ + dfl.long_fract &= 0x7FFFFFFF; + } + } + } + } else if (dfl.expo == 64) { + /* to be rounded */ + lsfract = dfl.long_fract << 8; + dfl.long_fract = 0; + } else { + /* fl.expo < 64 */ + dfl.long_fract = 0; + if (((m3 == 6) + && (dfl.sign == 0)) + || ((m3 == 7) + && (dfl.sign == 1))) { + dfl.long_fract++; + } + } + if (dfl.sign) { + /* negative */ + //FPSR |= 0x01000000; /* N bit on */ + i = -(int32)dfl.long_fract & 0xFFFFFFFF; + } else { + /* positive */ + i = (int32)dfl.long_fract & 0xFFFFFFFF; + } + } else { + /* zero */ + i = 0; + //FPSR |= 0x02000000; /* Z bit on */ + } - if (dfl.sign && i != 0) - i |= 0x80000000; + if (dfl.sign && i != 0) + i |= 0x80000000; - if (t == 1) - i = 0x4a430000; - if (t == 2) - i = 0x27e00000; - if (t == 3) - i = 0xF925FD00; + if (t == 1) + i = 0x4a430000; + if (t == 2) + i = 0x27e00000; + if (t == 3) + i = 0xF925FD00; - PutMap(MA, ((i >> 16) & 0xFFFF)); - PutMap(MA+1, (i & 0xFFFF)); - FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */ - FPSR |= ((PC - 2) & AMASK); - continue; - } - if ((IR & 0103777) == 0100050) { /* FAS Add single */ - if (!(fpu_unit.flags & UNIT_UP)) - continue; + PutMap(MA, ((i >> 16) & 0xFFFF)); + PutMap(MA+1, (i & 0xFFFF)); + FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */ + FPSR |= ((PC - 2) & AMASK); + continue; + } + if ((IR & 0103777) == 0100050) { /* FAS Add single */ + if (!(fpu_unit.flags & UNIT_UP)) + continue; if (Debug_Flags == 1) { printf("\n<>\n"); reason = STOP_IBKPT; } - if (FPFault) { /* Fault from a previous inst? */ - FPFault = 0; - t = (GetMap(040) + 1) & AMASK; /* Yes: 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-1) & AMASK)); - if (C) PutMap(t, (GetMap(t) | 0100000)); - PutMap(040, t); - PC = indirect(GetMap(045)); /* JMP indirect to 45 */ - continue; - } - i = (IR >> 13) & 3; - j = (IR >> 11) & 3; - FPSR &= 0xFCFFFFFF; /* Z+N bits off */ - get_sf(&sfl, &FPAC[i]); /* Place in working registers */ - get_sf(&sfl2, &FPAC[j]); - k = add_sf(&sfl2, &sfl, 1); /* Add the two */ - if (k) { - switch (k) { - case 1: - FPSR |= 0x40000000; /* OVF bit on */ - break; - case 2: - FPSR |= 0x20000000; /* UNF bit on */ - break; - } - } - store_sf(&sfl2, &FPAC[j]); /* put result in destination */ - if ((FPAC[j] & 0x00ffffffffffffff) == 0) - FPAC[j] = 0; - FPSR &= 0xFCFFFFFF; /* Z + N off */ - if (FPAC[j] == 0) - FPSR |= 0x02000000; /* Set Z */ - if (FPAC[j] & 0x8000000000000000) - FPSR |= 0x01000000; /* Set N */ - FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */ - FPSR |= ((PC - 1) & AMASK); + if (FPFault) { /* Fault from a previous inst? */ + FPFault = 0; + t = (GetMap(040) + 1) & AMASK; /* Yes: 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-1) & AMASK)); + if (C) PutMap(t, (GetMap(t) | 0100000)); + PutMap(040, t); + PC = indirect(GetMap(045)); /* JMP indirect to 45 */ + continue; + } + i = (IR >> 13) & 3; + j = (IR >> 11) & 3; + FPSR &= 0xFCFFFFFF; /* Z+N bits off */ + get_sf(&sfl, &FPAC[i]); /* Place in working registers */ + get_sf(&sfl2, &FPAC[j]); + k = add_sf(&sfl2, &sfl, 1); /* Add the two */ + if (k) { + switch (k) { + case 1: + FPSR |= 0x40000000; /* OVF bit on */ + break; + case 2: + FPSR |= 0x20000000; /* UNF bit on */ + break; + } + } + store_sf(&sfl2, &FPAC[j]); /* put result in destination */ + if ((FPAC[j] & 0x00ffffffffffffff) == 0) + FPAC[j] = 0; + FPSR &= 0xFCFFFFFF; /* Z + N off */ + if (FPAC[j] == 0) + FPSR |= 0x02000000; /* Set Z */ + if (FPAC[j] & 0x8000000000000000) + FPSR |= 0x01000000; /* Set N */ + FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */ + FPSR |= ((PC - 1) & AMASK); continue; } - if ((IR & 0103777) == 0101050) { /* FAMS Add single (memory) */ - if (!(fpu_unit.flags & UNIT_UP)) - continue; + if ((IR & 0103777) == 0101050) { /* FAMS Add single (memory) */ + if (!(fpu_unit.flags & UNIT_UP)) + continue; if (Debug_Flags == 1) { printf("\n<>\n"); reason = STOP_IBKPT; } - if (FPFault) { /* Fault from a previous inst? */ - FPFault = 0; - t = (GetMap(040) + 1) & AMASK; /* Yes: 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-1) & AMASK)); - if (C) PutMap(t, (GetMap(t) | 0100000)); - PutMap(040, t); - PC = indirect(GetMap(045)); /* JMP indirect to 45 */ - continue; - } - j = (IR >> 11) & 3; + if (FPFault) { /* Fault from a previous inst? */ + FPFault = 0; + t = (GetMap(040) + 1) & AMASK; /* Yes: 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-1) & AMASK)); + if (C) PutMap(t, (GetMap(t) | 0100000)); + PutMap(040, t); + PC = indirect(GetMap(045)); /* JMP indirect to 45 */ + continue; + } + j = (IR >> 11) & 3; MA = effective(PC, (IR >> 13) & 3, GetMap(PC)); - tempfp = ((t_uint64)GetMap(MA) << 48); - tempfp |= ((t_uint64)GetMap(MA + 1) << 32); - if ((tempfp & 0x00ffffffffffffff) == 0) - tempfp = 0; - FPSR &= 0xFCFFFFFF; /* Z+N bits off */ - get_sf(&sfl, &tempfp); /* Place in working registers */ - get_sf(&sfl2, &FPAC[j]); - k = add_sf(&sfl2, &sfl, 1); /* Add the two */ - if (k) { - switch (k) { - case 1: - FPSR |= 0x40000000; /* OVF bit on */ - break; - case 2: - FPSR |= 0x20000000; /* UNF bit on */ - break; - } - } - store_sf(&sfl2, &FPAC[j]); /* put result in destination */ - if ((FPAC[j] & 0x00ffffffffffffff) == 0) - FPAC[j] = 0; - FPSR &= 0xFCFFFFFF; /* Z + N off */ - if (FPAC[j] == 0) - FPSR |= 0x02000000; /* Set Z */ - if (FPAC[j] & 0x8000000000000000) - FPSR |= 0x01000000; /* Set N */ - FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */ - FPSR |= ((PC - 1) & AMASK); + tempfp = ((t_uint64)GetMap(MA) << 48); + tempfp |= ((t_uint64)GetMap(MA + 1) << 32); + if ((tempfp & 0x00ffffffffffffff) == 0) + tempfp = 0; + FPSR &= 0xFCFFFFFF; /* Z+N bits off */ + get_sf(&sfl, &tempfp); /* Place in working registers */ + get_sf(&sfl2, &FPAC[j]); + k = add_sf(&sfl2, &sfl, 1); /* Add the two */ + if (k) { + switch (k) { + case 1: + FPSR |= 0x40000000; /* OVF bit on */ + break; + case 2: + FPSR |= 0x20000000; /* UNF bit on */ + break; + } + } + store_sf(&sfl2, &FPAC[j]); /* put result in destination */ + if ((FPAC[j] & 0x00ffffffffffffff) == 0) + FPAC[j] = 0; + FPSR &= 0xFCFFFFFF; /* Z + N off */ + if (FPAC[j] == 0) + FPSR |= 0x02000000; /* Set Z */ + if (FPAC[j] & 0x8000000000000000) + FPSR |= 0x01000000; /* Set N */ + FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */ + FPSR |= ((PC - 1) & AMASK); PC = (PC + 1) & AMASK; continue; } - if ((IR & 0103777) == 0100150) { /* FAD Add double */ - if (!(fpu_unit.flags & UNIT_UP)) - continue; + if ((IR & 0103777) == 0100150) { /* FAD Add double */ + if (!(fpu_unit.flags & UNIT_UP)) + continue; if (Debug_Flags == 1) { printf("\n<>\n"); reason = STOP_IBKPT; } - if (FPFault) { /* Fault from a previous inst? */ - FPFault = 0; - t = (GetMap(040) + 1) & AMASK; /* Yes: 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-1) & AMASK)); - if (C) PutMap(t, (GetMap(t) | 0100000)); - PutMap(040, t); - PC = indirect(GetMap(045)); /* JMP indirect to 45 */ - continue; - } - i = (IR >> 13) & 3; - j = (IR >> 11) & 3; - FPSR &= 0xFCFFFFFF; /* Z+N bits off */ - get_lf(&dfl, &FPAC[i]); /* Place in working registers */ - get_lf(&dfl2, &FPAC[j]); - k = add_lf(&dfl2, &dfl, 1); /* Add the two */ - if (k) { - switch (k) { - case 1: - FPSR |= 0x40000000; /* OVF bit on */ - break; - case 2: - FPSR |= 0x20000000; /* UNF bit on */ - break; - } - } - store_lf(&dfl2, &FPAC[j]); /* put result in destination */ - if ((FPAC[j] & 0x00ffffffffffffff) == 0) - FPAC[j] = 0; - FPSR &= 0xFCFFFFFF; /* Z + N off */ - if (FPAC[j] == 0) - FPSR |= 0x02000000; /* Set Z */ - if (FPAC[j] & 0x8000000000000000) - FPSR |= 0x01000000; /* Set N */ - FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */ - FPSR |= ((PC - 1) & AMASK); + if (FPFault) { /* Fault from a previous inst? */ + FPFault = 0; + t = (GetMap(040) + 1) & AMASK; /* Yes: 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-1) & AMASK)); + if (C) PutMap(t, (GetMap(t) | 0100000)); + PutMap(040, t); + PC = indirect(GetMap(045)); /* JMP indirect to 45 */ + continue; + } + i = (IR >> 13) & 3; + j = (IR >> 11) & 3; + FPSR &= 0xFCFFFFFF; /* Z+N bits off */ + get_lf(&dfl, &FPAC[i]); /* Place in working registers */ + get_lf(&dfl2, &FPAC[j]); + k = add_lf(&dfl2, &dfl, 1); /* Add the two */ + if (k) { + switch (k) { + case 1: + FPSR |= 0x40000000; /* OVF bit on */ + break; + case 2: + FPSR |= 0x20000000; /* UNF bit on */ + break; + } + } + store_lf(&dfl2, &FPAC[j]); /* put result in destination */ + if ((FPAC[j] & 0x00ffffffffffffff) == 0) + FPAC[j] = 0; + FPSR &= 0xFCFFFFFF; /* Z + N off */ + if (FPAC[j] == 0) + FPSR |= 0x02000000; /* Set Z */ + if (FPAC[j] & 0x8000000000000000) + FPSR |= 0x01000000; /* Set N */ + FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */ + FPSR |= ((PC - 1) & AMASK); continue; } - if ((IR & 0103777) == 0101150) { /* FAMD Add double (memory) */ - if (!(fpu_unit.flags & UNIT_UP)) - continue; + if ((IR & 0103777) == 0101150) { /* FAMD Add double (memory) */ + if (!(fpu_unit.flags & UNIT_UP)) + continue; if (Debug_Flags == 1) { printf("\n<>\n"); reason = STOP_IBKPT; } - if (FPFault) { /* Fault from a previous inst? */ - FPFault = 0; - t = (GetMap(040) + 1) & AMASK; /* Yes: 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-1) & AMASK)); - if (C) PutMap(t, (GetMap(t) | 0100000)); - PutMap(040, t); - PC = indirect(GetMap(045)); /* JMP indirect to 45 */ - continue; - } - j = (IR >> 11) & 3; + if (FPFault) { /* Fault from a previous inst? */ + FPFault = 0; + t = (GetMap(040) + 1) & AMASK; /* Yes: 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-1) & AMASK)); + if (C) PutMap(t, (GetMap(t) | 0100000)); + PutMap(040, t); + PC = indirect(GetMap(045)); /* JMP indirect to 45 */ + continue; + } + j = (IR >> 11) & 3; MA = effective(PC, (IR >> 13) & 3, GetMap(PC)); - tempfp = ((t_uint64)GetMap(MA) << 48); - tempfp |= ((t_uint64)GetMap(MA + 1) << 32); - tempfp |= ((t_uint64)GetMap(MA + 2) << 16); - tempfp |= ((t_uint64)GetMap(MA + 3)); - if ((tempfp & 0x00ffffffffffffff) == 0) - tempfp = 0; - FPSR &= 0xFCFFFFFF; /* Z+N bits off */ - get_lf(&dfl, &tempfp); /* Place in working registers */ - get_lf(&dfl2, &FPAC[j]); - k = add_lf(&dfl2, &dfl, 1); /* Add the two */ - if (k) { - switch (k) { - case 1: - FPSR |= 0x40000000; /* OVF bit on */ - break; - case 2: - FPSR |= 0x20000000; /* UNF bit on */ - break; - } - } - store_lf(&dfl2, &FPAC[j]); /* put result in destination */ - if ((FPAC[j] & 0x00ffffffffffffff) == 0) - FPAC[j] = 0; - FPSR &= 0xFCFFFFFF; /* Z + N off */ - if (FPAC[j] == 0) - FPSR |= 0x02000000; /* Set Z */ - if (FPAC[j] & 0x8000000000000000) - FPSR |= 0x01000000; /* Set N */ - FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */ - FPSR |= ((PC - 1) & AMASK); + tempfp = ((t_uint64)GetMap(MA) << 48); + tempfp |= ((t_uint64)GetMap(MA + 1) << 32); + tempfp |= ((t_uint64)GetMap(MA + 2) << 16); + tempfp |= ((t_uint64)GetMap(MA + 3)); + if ((tempfp & 0x00ffffffffffffff) == 0) + tempfp = 0; + FPSR &= 0xFCFFFFFF; /* Z+N bits off */ + get_lf(&dfl, &tempfp); /* Place in working registers */ + get_lf(&dfl2, &FPAC[j]); + k = add_lf(&dfl2, &dfl, 1); /* Add the two */ + if (k) { + switch (k) { + case 1: + FPSR |= 0x40000000; /* OVF bit on */ + break; + case 2: + FPSR |= 0x20000000; /* UNF bit on */ + break; + } + } + store_lf(&dfl2, &FPAC[j]); /* put result in destination */ + if ((FPAC[j] & 0x00ffffffffffffff) == 0) + FPAC[j] = 0; + FPSR &= 0xFCFFFFFF; /* Z + N off */ + if (FPAC[j] == 0) + FPSR |= 0x02000000; /* Set Z */ + if (FPAC[j] & 0x8000000000000000) + FPSR |= 0x01000000; /* Set N */ + FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */ + FPSR |= ((PC - 1) & AMASK); PC = (PC + 1) & AMASK; continue; } - if ((IR & 0103777) == 0100250) { /* FSS Sub single to AC */ - if (!(fpu_unit.flags & UNIT_UP)) - continue; + if ((IR & 0103777) == 0100250) { /* FSS Sub single to AC */ + if (!(fpu_unit.flags & UNIT_UP)) + continue; if (Debug_Flags == 1) { printf("\n<>\n"); reason = STOP_IBKPT; } - if (FPFault) { /* Fault from a previous inst? */ - FPFault = 0; - t = (GetMap(040) + 1) & AMASK; /* Yes: 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-1) & AMASK)); - if (C) PutMap(t, (GetMap(t) | 0100000)); - PutMap(040, t); - PC = indirect(GetMap(045)); /* JMP indirect to 45 */ - continue; - } - i = (IR >> 13) & 3; - j = (IR >> 11) & 3; - FPSR &= 0xFCFFFFFF; /* Z+N bits off */ - get_sf(&sfl, &FPAC[i]); /* Place in working registers */ - get_sf(&sfl2, &FPAC[j]); - sfl.sign = ! (sfl.sign); /* invert sign of 2nd operand */ - k = add_sf(&sfl2, &sfl, 1); /* Add the two */ - if (k) { - switch (k) { - case 1: - FPSR |= 0x40000000; /* OVF bit on */ - break; - case 2: - FPSR |= 0x20000000; /* UNF bit on */ - break; - } - } - store_sf(&sfl2, &FPAC[j]); /* put result in destination */ - if ((FPAC[j] & 0x00ffffffffffffff) == 0) - FPAC[j] = 0; - FPSR &= 0xFCFFFFFF; /* Z + N off */ - if (FPAC[j] == 0) - FPSR |= 0x02000000; /* Set Z */ - if (FPAC[j] & 0x8000000000000000) - FPSR |= 0x01000000; /* Set N */ - FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */ - FPSR |= ((PC - 1) & AMASK); + if (FPFault) { /* Fault from a previous inst? */ + FPFault = 0; + t = (GetMap(040) + 1) & AMASK; /* Yes: 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-1) & AMASK)); + if (C) PutMap(t, (GetMap(t) | 0100000)); + PutMap(040, t); + PC = indirect(GetMap(045)); /* JMP indirect to 45 */ + continue; + } + i = (IR >> 13) & 3; + j = (IR >> 11) & 3; + FPSR &= 0xFCFFFFFF; /* Z+N bits off */ + get_sf(&sfl, &FPAC[i]); /* Place in working registers */ + get_sf(&sfl2, &FPAC[j]); + sfl.sign = ! (sfl.sign); /* invert sign of 2nd operand */ + k = add_sf(&sfl2, &sfl, 1); /* Add the two */ + if (k) { + switch (k) { + case 1: + FPSR |= 0x40000000; /* OVF bit on */ + break; + case 2: + FPSR |= 0x20000000; /* UNF bit on */ + break; + } + } + store_sf(&sfl2, &FPAC[j]); /* put result in destination */ + if ((FPAC[j] & 0x00ffffffffffffff) == 0) + FPAC[j] = 0; + FPSR &= 0xFCFFFFFF; /* Z + N off */ + if (FPAC[j] == 0) + FPSR |= 0x02000000; /* Set Z */ + if (FPAC[j] & 0x8000000000000000) + FPSR |= 0x01000000; /* Set N */ + FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */ + FPSR |= ((PC - 1) & AMASK); continue; } - if ((IR & 0103777) == 0101250) { /* FSMS Sub single (memory) */ - if (!(fpu_unit.flags & UNIT_UP)) - continue; + if ((IR & 0103777) == 0101250) { /* FSMS Sub single (memory) */ + if (!(fpu_unit.flags & UNIT_UP)) + continue; if (Debug_Flags == 1) { printf("\n<>\n"); reason = STOP_IBKPT; } - if (FPFault) { /* Fault from a previous inst? */ - FPFault = 0; - t = (GetMap(040) + 1) & AMASK; /* Yes: 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-1) & AMASK)); - if (C) PutMap(t, (GetMap(t) | 0100000)); - PutMap(040, t); - PC = indirect(GetMap(045)); /* JMP indirect to 45 */ - continue; - } - j = (IR >> 11) & 3; + if (FPFault) { /* Fault from a previous inst? */ + FPFault = 0; + t = (GetMap(040) + 1) & AMASK; /* Yes: 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-1) & AMASK)); + if (C) PutMap(t, (GetMap(t) | 0100000)); + PutMap(040, t); + PC = indirect(GetMap(045)); /* JMP indirect to 45 */ + continue; + } + j = (IR >> 11) & 3; MA = effective(PC, (IR >> 13) & 3, GetMap(PC)); - tempfp = ((t_uint64)GetMap(MA) << 48); - tempfp |= ((t_uint64)GetMap(MA + 1) << 32); - if ((tempfp & 0x00ffffffffffffff) == 0) - tempfp = 0; - FPSR &= 0xFCFFFFFF; /* Z+N bits off */ - get_sf(&sfl, &tempfp); /* Place in working registers */ - get_sf(&sfl2, &FPAC[j]); - sfl.sign = ! (sfl.sign); /* invert sign of 2nd operand */ - k = add_sf(&sfl2, &sfl, 1); /* Add the two */ - if (k) { - switch (k) { - case 1: - FPSR |= 0x40000000; /* OVF bit on */ - break; - case 2: - FPSR |= 0x20000000; /* UNF bit on */ - break; - } - } - store_sf(&sfl2, &FPAC[j]); /* put result in destination */ - if ((FPAC[j] & 0x00ffffffffffffff) == 0) - FPAC[j] = 0; - FPSR &= 0xFCFFFFFF; /* Z + N off */ - if (FPAC[j] == 0) - FPSR |= 0x02000000; /* Set Z */ - if (FPAC[j] & 0x8000000000000000) - FPSR |= 0x01000000; /* Set N */ - FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */ - FPSR |= ((PC - 1) & AMASK); + tempfp = ((t_uint64)GetMap(MA) << 48); + tempfp |= ((t_uint64)GetMap(MA + 1) << 32); + if ((tempfp & 0x00ffffffffffffff) == 0) + tempfp = 0; + FPSR &= 0xFCFFFFFF; /* Z+N bits off */ + get_sf(&sfl, &tempfp); /* Place in working registers */ + get_sf(&sfl2, &FPAC[j]); + sfl.sign = ! (sfl.sign); /* invert sign of 2nd operand */ + k = add_sf(&sfl2, &sfl, 1); /* Add the two */ + if (k) { + switch (k) { + case 1: + FPSR |= 0x40000000; /* OVF bit on */ + break; + case 2: + FPSR |= 0x20000000; /* UNF bit on */ + break; + } + } + store_sf(&sfl2, &FPAC[j]); /* put result in destination */ + if ((FPAC[j] & 0x00ffffffffffffff) == 0) + FPAC[j] = 0; + FPSR &= 0xFCFFFFFF; /* Z + N off */ + if (FPAC[j] == 0) + FPSR |= 0x02000000; /* Set Z */ + if (FPAC[j] & 0x8000000000000000) + FPSR |= 0x01000000; /* Set N */ + FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */ + FPSR |= ((PC - 1) & AMASK); PC = (PC + 1) & AMASK; continue; } - if ((IR & 0103777) == 0100350) { /* FSD Sub double from AC */ - if (!(fpu_unit.flags & UNIT_UP)) - continue; + if ((IR & 0103777) == 0100350) { /* FSD Sub double from AC */ + if (!(fpu_unit.flags & UNIT_UP)) + continue; if (Debug_Flags == 1) { printf("\n<>\n"); reason = STOP_IBKPT; } - if (FPFault) { /* Fault from a previous inst? */ - FPFault = 0; - t = (GetMap(040) + 1) & AMASK; /* Yes: 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-1) & AMASK)); - if (C) PutMap(t, (GetMap(t) | 0100000)); - PutMap(040, t); - PC = indirect(GetMap(045)); /* JMP indirect to 45 */ - continue; - } - i = (IR >> 13) & 3; - j = (IR >> 11) & 3; - FPSR &= 0xFCFFFFFF; /* Z+N bits off */ - get_lf(&dfl, &FPAC[i]); /* Place in working registers */ - get_lf(&dfl2, &FPAC[j]); - dfl.sign = ! (dfl.sign); /* invert sign of 2nd operand */ - k = add_lf(&dfl2, &dfl, 1); /* Add the two */ - if (k) { - switch (k) { - case 1: - FPSR |= 0x40000000; /* OVF bit on */ - break; - case 2: - FPSR |= 0x20000000; /* UNF bit on */ - break; - } - } - store_lf(&dfl2, &FPAC[j]); /* put result in destination */ - if ((FPAC[j] & 0x00ffffffffffffff) == 0) - FPAC[j] = 0; - FPSR &= 0xFCFFFFFF; /* Z + N off */ - if (FPAC[j] == 0) - FPSR |= 0x02000000; /* Set Z */ - if (FPAC[j] & 0x8000000000000000) - FPSR |= 0x01000000; /* Set N */ - FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */ - FPSR |= ((PC - 1) & AMASK); + if (FPFault) { /* Fault from a previous inst? */ + FPFault = 0; + t = (GetMap(040) + 1) & AMASK; /* Yes: 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-1) & AMASK)); + if (C) PutMap(t, (GetMap(t) | 0100000)); + PutMap(040, t); + PC = indirect(GetMap(045)); /* JMP indirect to 45 */ + continue; + } + i = (IR >> 13) & 3; + j = (IR >> 11) & 3; + FPSR &= 0xFCFFFFFF; /* Z+N bits off */ + get_lf(&dfl, &FPAC[i]); /* Place in working registers */ + get_lf(&dfl2, &FPAC[j]); + dfl.sign = ! (dfl.sign); /* invert sign of 2nd operand */ + k = add_lf(&dfl2, &dfl, 1); /* Add the two */ + if (k) { + switch (k) { + case 1: + FPSR |= 0x40000000; /* OVF bit on */ + break; + case 2: + FPSR |= 0x20000000; /* UNF bit on */ + break; + } + } + store_lf(&dfl2, &FPAC[j]); /* put result in destination */ + if ((FPAC[j] & 0x00ffffffffffffff) == 0) + FPAC[j] = 0; + FPSR &= 0xFCFFFFFF; /* Z + N off */ + if (FPAC[j] == 0) + FPSR |= 0x02000000; /* Set Z */ + if (FPAC[j] & 0x8000000000000000) + FPSR |= 0x01000000; /* Set N */ + FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */ + FPSR |= ((PC - 1) & AMASK); continue; } - if ((IR & 0103777) == 0101350) { /* FSMD Sub double from memory */ - if (!(fpu_unit.flags & UNIT_UP)) - continue; + if ((IR & 0103777) == 0101350) { /* FSMD Sub double from memory */ + if (!(fpu_unit.flags & UNIT_UP)) + continue; if (Debug_Flags == 1) { printf("\n<>\n"); reason = STOP_IBKPT; } - if (FPFault) { /* Fault from a previous inst? */ - FPFault = 0; - t = (GetMap(040) + 1) & AMASK; /* Yes: 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-1) & AMASK)); - if (C) PutMap(t, (GetMap(t) | 0100000)); - PutMap(040, t); - PC = indirect(GetMap(045)); /* JMP indirect to 45 */ - continue; - } - j = (IR >> 11) & 3; + if (FPFault) { /* Fault from a previous inst? */ + FPFault = 0; + t = (GetMap(040) + 1) & AMASK; /* Yes: 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-1) & AMASK)); + if (C) PutMap(t, (GetMap(t) | 0100000)); + PutMap(040, t); + PC = indirect(GetMap(045)); /* JMP indirect to 45 */ + continue; + } + j = (IR >> 11) & 3; MA = effective(PC, (IR >> 13) & 3, GetMap(PC)); - tempfp = ((t_uint64)GetMap(MA) << 48); - tempfp |= ((t_uint64)GetMap(MA + 1) << 32); - tempfp |= ((t_uint64)GetMap(MA + 2) << 16); - tempfp |= ((t_uint64)GetMap(MA + 3)); - if ((tempfp & 0x00ffffffffffffff) == 0) - tempfp = 0; - FPSR &= 0xFCFFFFFF; /* Z+N bits off */ - get_lf(&dfl, &tempfp); /* Place in working registers */ - get_lf(&dfl2, &FPAC[j]); - dfl.sign = ! (dfl.sign); /* invert sign of 2nd operand */ - k = add_lf(&dfl2, &dfl, 1); /* Add the two */ - if (k) { - switch (k) { - case 1: - FPSR |= 0x40000000; /* OVF bit on */ - break; - case 2: - FPSR |= 0x20000000; /* UNF bit on */ - break; - } - } - store_lf(&dfl2, &FPAC[j]); /* put result in destination */ - if ((FPAC[j] & 0x00ffffffffffffff) == 0) - FPAC[j] = 0; - FPSR &= 0xFCFFFFFF; /* Z + N off */ - if (FPAC[j] == 0) - FPSR |= 0x02000000; /* Set Z */ - if (FPAC[j] & 0x8000000000000000) - FPSR |= 0x01000000; /* Set N */ - FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */ - FPSR |= ((PC - 1) & AMASK); + tempfp = ((t_uint64)GetMap(MA) << 48); + tempfp |= ((t_uint64)GetMap(MA + 1) << 32); + tempfp |= ((t_uint64)GetMap(MA + 2) << 16); + tempfp |= ((t_uint64)GetMap(MA + 3)); + if ((tempfp & 0x00ffffffffffffff) == 0) + tempfp = 0; + FPSR &= 0xFCFFFFFF; /* Z+N bits off */ + get_lf(&dfl, &tempfp); /* Place in working registers */ + get_lf(&dfl2, &FPAC[j]); + dfl.sign = ! (dfl.sign); /* invert sign of 2nd operand */ + k = add_lf(&dfl2, &dfl, 1); /* Add the two */ + if (k) { + switch (k) { + case 1: + FPSR |= 0x40000000; /* OVF bit on */ + break; + case 2: + FPSR |= 0x20000000; /* UNF bit on */ + break; + } + } + store_lf(&dfl2, &FPAC[j]); /* put result in destination */ + if ((FPAC[j] & 0x00ffffffffffffff) == 0) + FPAC[j] = 0; + FPSR &= 0xFCFFFFFF; /* Z + N off */ + if (FPAC[j] == 0) + FPSR |= 0x02000000; /* Set Z */ + if (FPAC[j] & 0x8000000000000000) + FPSR |= 0x01000000; /* Set N */ + FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */ + FPSR |= ((PC - 1) & AMASK); PC = (PC + 1) & AMASK; continue; } - if ((IR & 0103777) == 0100450) { /* FMS Mult single by AC */ - if (!(fpu_unit.flags & UNIT_UP)) - continue; + if ((IR & 0103777) == 0100450) { /* FMS Mult single by AC */ + if (!(fpu_unit.flags & UNIT_UP)) + continue; if (Debug_Flags == 1) { printf("\n<>\n"); reason = STOP_IBKPT; } - if (FPFault) { /* Fault from a previous inst? */ - FPFault = 0; - t = (GetMap(040) + 1) & AMASK; /* Yes: 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-1) & AMASK)); - if (C) PutMap(t, (GetMap(t) | 0100000)); - PutMap(040, t); - PC = indirect(GetMap(045)); /* JMP indirect to 45 */ - continue; - } - i = (IR >> 13) & 3; - j = (IR >> 11) & 3; - FPSR &= 0xFCFFFFFF; /* Z+N bits off */ - get_sf(&sfl, &FPAC[i]); /* Place in working registers */ - get_sf(&sfl2, &FPAC[j]); - k = mul_sf(&sfl2, &sfl); /* Multiply */ - if (k) { - switch (k) { - case 1: - FPSR |= 0x40000000; /* OVF bit on */ - break; - case 2: - FPSR |= 0x20000000; /* UNF bit on */ - break; - } - } - store_sf(&sfl2, &FPAC[j]); /* put result in destination */ - if ((FPAC[j] & 0x00ffffffffffffff) == 0) - FPAC[j] = 0; - FPSR &= 0xFCFFFFFF; /* Z + N off */ - if (FPAC[j] == 0) - FPSR |= 0x02000000; /* Set Z */ - if (FPAC[j] & 0x8000000000000000) - FPSR |= 0x01000000; /* Set N */ - FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */ - FPSR |= ((PC - 1) & AMASK); + if (FPFault) { /* Fault from a previous inst? */ + FPFault = 0; + t = (GetMap(040) + 1) & AMASK; /* Yes: 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-1) & AMASK)); + if (C) PutMap(t, (GetMap(t) | 0100000)); + PutMap(040, t); + PC = indirect(GetMap(045)); /* JMP indirect to 45 */ + continue; + } + i = (IR >> 13) & 3; + j = (IR >> 11) & 3; + FPSR &= 0xFCFFFFFF; /* Z+N bits off */ + get_sf(&sfl, &FPAC[i]); /* Place in working registers */ + get_sf(&sfl2, &FPAC[j]); + k = mul_sf(&sfl2, &sfl); /* Multiply */ + if (k) { + switch (k) { + case 1: + FPSR |= 0x40000000; /* OVF bit on */ + break; + case 2: + FPSR |= 0x20000000; /* UNF bit on */ + break; + } + } + store_sf(&sfl2, &FPAC[j]); /* put result in destination */ + if ((FPAC[j] & 0x00ffffffffffffff) == 0) + FPAC[j] = 0; + FPSR &= 0xFCFFFFFF; /* Z + N off */ + if (FPAC[j] == 0) + FPSR |= 0x02000000; /* Set Z */ + if (FPAC[j] & 0x8000000000000000) + FPSR |= 0x01000000; /* Set N */ + FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */ + FPSR |= ((PC - 1) & AMASK); continue; } - if ((IR & 0103777) == 0101450) { /* FMMS Mult single by memory */ - if (!(fpu_unit.flags & UNIT_UP)) - continue; + if ((IR & 0103777) == 0101450) { /* FMMS Mult single by memory */ + if (!(fpu_unit.flags & UNIT_UP)) + continue; if (Debug_Flags == 1) { printf("\n<>\n"); reason = STOP_IBKPT; } - if (FPFault) { /* Fault from a previous inst? */ - FPFault = 0; - t = (GetMap(040) + 1) & AMASK; /* Yes: 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-1) & AMASK)); - if (C) PutMap(t, (GetMap(t) | 0100000)); - PutMap(040, t); - PC = indirect(GetMap(045)); /* JMP indirect to 45 */ - continue; - } - j = (IR >> 11) & 3; + if (FPFault) { /* Fault from a previous inst? */ + FPFault = 0; + t = (GetMap(040) + 1) & AMASK; /* Yes: 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-1) & AMASK)); + if (C) PutMap(t, (GetMap(t) | 0100000)); + PutMap(040, t); + PC = indirect(GetMap(045)); /* JMP indirect to 45 */ + continue; + } + j = (IR >> 11) & 3; MA = effective(PC, (IR >> 13) & 3, GetMap(PC)); - tempfp = ((t_uint64)GetMap(MA) << 48); - tempfp |= ((t_uint64)GetMap(MA + 1) << 32); - if ((tempfp & 0x00ffffffffffffff) == 0) - tempfp = 0; - FPSR &= 0xFCFFFFFF; /* Z+N bits off */ - get_sf(&sfl, &tempfp); /* Place in working registers */ - get_sf(&sfl2, &FPAC[j]); - k = mul_sf(&sfl2, &sfl); /* Multiply */ - if (k) { - switch (k) { - case 1: - FPSR |= 0x40000000; /* OVF bit on */ - break; - case 2: - FPSR |= 0x20000000; /* UNF bit on */ - break; - } - } - store_sf(&sfl2, &FPAC[j]); /* put result in destination */ - if ((FPAC[j] & 0x00ffffffffffffff) == 0) - FPAC[j] = 0; - FPSR &= 0xFCFFFFFF; /* Z + N off */ - if (FPAC[j] == 0) - FPSR |= 0x02000000; /* Set Z */ - if (FPAC[j] & 0x8000000000000000) - FPSR |= 0x01000000; /* Set N */ - FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */ - FPSR |= ((PC - 1) & AMASK); + tempfp = ((t_uint64)GetMap(MA) << 48); + tempfp |= ((t_uint64)GetMap(MA + 1) << 32); + if ((tempfp & 0x00ffffffffffffff) == 0) + tempfp = 0; + FPSR &= 0xFCFFFFFF; /* Z+N bits off */ + get_sf(&sfl, &tempfp); /* Place in working registers */ + get_sf(&sfl2, &FPAC[j]); + k = mul_sf(&sfl2, &sfl); /* Multiply */ + if (k) { + switch (k) { + case 1: + FPSR |= 0x40000000; /* OVF bit on */ + break; + case 2: + FPSR |= 0x20000000; /* UNF bit on */ + break; + } + } + store_sf(&sfl2, &FPAC[j]); /* put result in destination */ + if ((FPAC[j] & 0x00ffffffffffffff) == 0) + FPAC[j] = 0; + FPSR &= 0xFCFFFFFF; /* Z + N off */ + if (FPAC[j] == 0) + FPSR |= 0x02000000; /* Set Z */ + if (FPAC[j] & 0x8000000000000000) + FPSR |= 0x01000000; /* Set N */ + FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */ + FPSR |= ((PC - 1) & AMASK); PC = (PC + 1) & AMASK; continue; } - if ((IR & 0103777) == 0100550) { /* FMD Mult double by AC */ - if (!(fpu_unit.flags & UNIT_UP)) - continue; + if ((IR & 0103777) == 0100550) { /* FMD Mult double by AC */ + if (!(fpu_unit.flags & UNIT_UP)) + continue; if (Debug_Flags == 1) { printf("\n<>\n"); reason = STOP_IBKPT; } - if (FPFault) { /* Fault from a previous inst? */ - FPFault = 0; - t = (GetMap(040) + 1) & AMASK; /* Yes: 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-1) & AMASK)); - if (C) PutMap(t, (GetMap(t) | 0100000)); - PutMap(040, t); - PC = indirect(GetMap(045)); /* JMP indirect to 45 */ - continue; - } - i = (IR >> 13) & 3; - j = (IR >> 11) & 3; - FPSR &= 0xFCFFFFFF; /* Z+N bits off */ - get_lf(&dfl, &FPAC[i]); /* Place in working registers */ - get_lf(&dfl2, &FPAC[j]); - k = mul_lf(&dfl2, &dfl); /* Multiply */ - if (k) { - switch (k) { - case 1: - FPSR |= 0x40000000; /* OVF bit on */ - break; - case 2: - FPSR |= 0x20000000; /* UNF bit on */ - break; - } - } - store_lf(&dfl2, &FPAC[j]); /* put result in destination */ - if ((FPAC[j] & 0x00ffffffffffffff) == 0) - FPAC[j] = 0; - FPSR &= 0xFCFFFFFF; /* Z + N off */ - if (FPAC[j] == 0) - FPSR |= 0x02000000; /* Set Z */ - if (FPAC[j] & 0x8000000000000000) - FPSR |= 0x01000000; /* Set N */ - FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */ - FPSR |= ((PC - 1) & AMASK); + if (FPFault) { /* Fault from a previous inst? */ + FPFault = 0; + t = (GetMap(040) + 1) & AMASK; /* Yes: 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-1) & AMASK)); + if (C) PutMap(t, (GetMap(t) | 0100000)); + PutMap(040, t); + PC = indirect(GetMap(045)); /* JMP indirect to 45 */ + continue; + } + i = (IR >> 13) & 3; + j = (IR >> 11) & 3; + FPSR &= 0xFCFFFFFF; /* Z+N bits off */ + get_lf(&dfl, &FPAC[i]); /* Place in working registers */ + get_lf(&dfl2, &FPAC[j]); + k = mul_lf(&dfl2, &dfl); /* Multiply */ + if (k) { + switch (k) { + case 1: + FPSR |= 0x40000000; /* OVF bit on */ + break; + case 2: + FPSR |= 0x20000000; /* UNF bit on */ + break; + } + } + store_lf(&dfl2, &FPAC[j]); /* put result in destination */ + if ((FPAC[j] & 0x00ffffffffffffff) == 0) + FPAC[j] = 0; + FPSR &= 0xFCFFFFFF; /* Z + N off */ + if (FPAC[j] == 0) + FPSR |= 0x02000000; /* Set Z */ + if (FPAC[j] & 0x8000000000000000) + FPSR |= 0x01000000; /* Set N */ + FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */ + FPSR |= ((PC - 1) & AMASK); continue; } - if ((IR & 0103777) == 0101550) { /* FMMD Mult double by memory */ - if (!(fpu_unit.flags & UNIT_UP)) - continue; + if ((IR & 0103777) == 0101550) { /* FMMD Mult double by memory */ + if (!(fpu_unit.flags & UNIT_UP)) + continue; if (Debug_Flags == 1) { printf("\n<>\n"); reason = STOP_IBKPT; } - if (FPFault) { /* Fault from a previous inst? */ - FPFault = 0; - t = (GetMap(040) + 1) & AMASK; /* Yes: 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-1) & AMASK)); - if (C) PutMap(t, (GetMap(t) | 0100000)); - PutMap(040, t); - PC = indirect(GetMap(045)); /* JMP indirect to 45 */ - continue; - } - j = (IR >> 11) & 3; + if (FPFault) { /* Fault from a previous inst? */ + FPFault = 0; + t = (GetMap(040) + 1) & AMASK; /* Yes: 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-1) & AMASK)); + if (C) PutMap(t, (GetMap(t) | 0100000)); + PutMap(040, t); + PC = indirect(GetMap(045)); /* JMP indirect to 45 */ + continue; + } + j = (IR >> 11) & 3; MA = effective(PC, (IR >> 13) & 3, GetMap(PC)); - tempfp = ((t_uint64)GetMap(MA) << 48); - tempfp |= ((t_uint64)GetMap(MA + 1) << 32); - tempfp |= ((t_uint64)GetMap(MA + 2) << 16); - tempfp |= ((t_uint64)GetMap(MA + 3)); - if ((tempfp & 0x00ffffffffffffff) == 0) - tempfp = 0; - FPSR &= 0xFCFFFFFF; /* Z+N bits off */ - get_lf(&dfl, &tempfp); /* Place in working registers */ - get_lf(&dfl2, &FPAC[j]); - k = mul_lf(&dfl2, &dfl); /* Multiply */ - if (k) { - switch (k) { - case 1: - FPSR |= 0x40000000; /* OVF bit on */ - break; - case 2: - FPSR |= 0x20000000; /* UNF bit on */ - break; - } - } - store_lf(&dfl2, &FPAC[j]); /* put result in destination */ - if ((FPAC[j] & 0x00ffffffffffffff) == 0) - FPAC[j] = 0; - FPSR &= 0xFCFFFFFF; /* Z + N off */ - if (FPAC[j] == 0) - FPSR |= 0x02000000; /* Set Z */ - if (FPAC[j] & 0x8000000000000000) - FPSR |= 0x01000000; /* Set N */ - FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */ - FPSR |= ((PC - 1) & AMASK); + tempfp = ((t_uint64)GetMap(MA) << 48); + tempfp |= ((t_uint64)GetMap(MA + 1) << 32); + tempfp |= ((t_uint64)GetMap(MA + 2) << 16); + tempfp |= ((t_uint64)GetMap(MA + 3)); + if ((tempfp & 0x00ffffffffffffff) == 0) + tempfp = 0; + FPSR &= 0xFCFFFFFF; /* Z+N bits off */ + get_lf(&dfl, &tempfp); /* Place in working registers */ + get_lf(&dfl2, &FPAC[j]); + k = mul_lf(&dfl2, &dfl); /* Multiply */ + if (k) { + switch (k) { + case 1: + FPSR |= 0x40000000; /* OVF bit on */ + break; + case 2: + FPSR |= 0x20000000; /* UNF bit on */ + break; + } + } + store_lf(&dfl2, &FPAC[j]); /* put result in destination */ + if ((FPAC[j] & 0x00ffffffffffffff) == 0) + FPAC[j] = 0; + FPSR &= 0xFCFFFFFF; /* Z + N off */ + if (FPAC[j] == 0) + FPSR |= 0x02000000; /* Set Z */ + if (FPAC[j] & 0x8000000000000000) + FPSR |= 0x01000000; /* Set N */ + FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */ + FPSR |= ((PC - 1) & AMASK); PC = (PC + 1) & AMASK; continue; } - if ((IR & 0103777) == 0100650) { /* FDS Div single by AC */ - if (!(fpu_unit.flags & UNIT_UP)) - continue; + if ((IR & 0103777) == 0100650) { /* FDS Div single by AC */ + if (!(fpu_unit.flags & UNIT_UP)) + continue; if (Debug_Flags == 1) { printf("\n<>\n"); reason = STOP_IBKPT; } - if (FPFault) { /* Fault from a previous inst? */ - FPFault = 0; - t = (GetMap(040) + 1) & AMASK; /* Yes: 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-1) & AMASK)); - if (C) PutMap(t, (GetMap(t) | 0100000)); - PutMap(040, t); - PC = indirect(GetMap(045)); /* JMP indirect to 45 */ - continue; - } - i = (IR >> 13) & 3; - j = (IR >> 11) & 3; - FPSR &= 0xFCFFFFFF; /* Z+N bits off */ - get_sf(&sfl, &FPAC[i]); /* Place in working registers */ - get_sf(&sfl2, &FPAC[j]); - k = div_sf(&sfl2, &sfl); /* Divide */ - if (k) { - switch (k) { - case 1: - FPSR |= 0x40000000; /* OVF bit on */ - break; - case 2: - FPSR |= 0x20000000; /* UNF bit on */ - break; - case 3: - FPSR |= 0x10000000; /* DVZ bit on */ - break; - } - } - store_sf(&sfl2, &FPAC[j]); /* put result in destination */ - if ((FPAC[j] & 0x00ffffffffffffff) == 0) - FPAC[j] = 0; - FPSR &= 0xFCFFFFFF; /* Z + N off */ - if (FPAC[j] == 0) - FPSR |= 0x02000000; /* Set Z */ - if (FPAC[j] & 0x8000000000000000) - FPSR |= 0x01000000; /* Set N */ - FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */ - FPSR |= ((PC - 1) & AMASK); + if (FPFault) { /* Fault from a previous inst? */ + FPFault = 0; + t = (GetMap(040) + 1) & AMASK; /* Yes: 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-1) & AMASK)); + if (C) PutMap(t, (GetMap(t) | 0100000)); + PutMap(040, t); + PC = indirect(GetMap(045)); /* JMP indirect to 45 */ + continue; + } + i = (IR >> 13) & 3; + j = (IR >> 11) & 3; + FPSR &= 0xFCFFFFFF; /* Z+N bits off */ + get_sf(&sfl, &FPAC[i]); /* Place in working registers */ + get_sf(&sfl2, &FPAC[j]); + k = div_sf(&sfl2, &sfl); /* Divide */ + if (k) { + switch (k) { + case 1: + FPSR |= 0x40000000; /* OVF bit on */ + break; + case 2: + FPSR |= 0x20000000; /* UNF bit on */ + break; + case 3: + FPSR |= 0x10000000; /* DVZ bit on */ + break; + } + } + store_sf(&sfl2, &FPAC[j]); /* put result in destination */ + if ((FPAC[j] & 0x00ffffffffffffff) == 0) + FPAC[j] = 0; + FPSR &= 0xFCFFFFFF; /* Z + N off */ + if (FPAC[j] == 0) + FPSR |= 0x02000000; /* Set Z */ + if (FPAC[j] & 0x8000000000000000) + FPSR |= 0x01000000; /* Set N */ + FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */ + FPSR |= ((PC - 1) & AMASK); continue; } - if ((IR & 0103777) == 0101650) { /* FDMS Div single by memory */ - if (!(fpu_unit.flags & UNIT_UP)) - continue; + if ((IR & 0103777) == 0101650) { /* FDMS Div single by memory */ + if (!(fpu_unit.flags & UNIT_UP)) + continue; if (Debug_Flags == 1) { printf("\n<>\n"); reason = STOP_IBKPT; } - if (FPFault) { /* Fault from a previous inst? */ - FPFault = 0; - t = (GetMap(040) + 1) & AMASK; /* Yes: 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-1) & AMASK)); - if (C) PutMap(t, (GetMap(t) | 0100000)); - PutMap(040, t); - PC = indirect(GetMap(045)); /* JMP indirect to 45 */ - continue; - } - j = (IR >> 11) & 3; + if (FPFault) { /* Fault from a previous inst? */ + FPFault = 0; + t = (GetMap(040) + 1) & AMASK; /* Yes: 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-1) & AMASK)); + if (C) PutMap(t, (GetMap(t) | 0100000)); + PutMap(040, t); + PC = indirect(GetMap(045)); /* JMP indirect to 45 */ + continue; + } + j = (IR >> 11) & 3; MA = effective(PC, (IR >> 13) & 3, GetMap(PC)); - tempfp = ((t_uint64)GetMap(MA) << 48); - tempfp |= ((t_uint64)GetMap(MA + 1) << 32); - if ((tempfp & 0x00ffffffffffffff) == 0) - tempfp = 0; - FPSR &= 0xFCFFFFFF; /* Z+N bits off */ - get_sf(&sfl, &tempfp); /* Place in working registers */ - get_sf(&sfl2, &FPAC[j]); - k = div_sf(&sfl2, &sfl); /* Divide */ - if (k) { - switch (k) { - case 1: - FPSR |= 0x40000000; /* OVF bit on */ - break; - case 2: - FPSR |= 0x20000000; /* UNF bit on */ - break; - case 3: - FPSR |= 0x10000000; /* DVZ bit on */ - break; - } - } - store_sf(&sfl2, &FPAC[j]); /* put result in destination */ - if ((FPAC[j] & 0x00ffffffffffffff) == 0) - FPAC[j] = 0; - FPSR &= 0xFCFFFFFF; /* Z + N off */ - if (FPAC[j] == 0) - FPSR |= 0x02000000; /* Set Z */ - if (FPAC[j] & 0x8000000000000000) - FPSR |= 0x01000000; /* Set N */ - FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */ - FPSR |= ((PC - 1) & AMASK); + tempfp = ((t_uint64)GetMap(MA) << 48); + tempfp |= ((t_uint64)GetMap(MA + 1) << 32); + if ((tempfp & 0x00ffffffffffffff) == 0) + tempfp = 0; + FPSR &= 0xFCFFFFFF; /* Z+N bits off */ + get_sf(&sfl, &tempfp); /* Place in working registers */ + get_sf(&sfl2, &FPAC[j]); + k = div_sf(&sfl2, &sfl); /* Divide */ + if (k) { + switch (k) { + case 1: + FPSR |= 0x40000000; /* OVF bit on */ + break; + case 2: + FPSR |= 0x20000000; /* UNF bit on */ + break; + case 3: + FPSR |= 0x10000000; /* DVZ bit on */ + break; + } + } + store_sf(&sfl2, &FPAC[j]); /* put result in destination */ + if ((FPAC[j] & 0x00ffffffffffffff) == 0) + FPAC[j] = 0; + FPSR &= 0xFCFFFFFF; /* Z + N off */ + if (FPAC[j] == 0) + FPSR |= 0x02000000; /* Set Z */ + if (FPAC[j] & 0x8000000000000000) + FPSR |= 0x01000000; /* Set N */ + FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */ + FPSR |= ((PC - 1) & AMASK); PC = (PC + 1) & AMASK; continue; } - if ((IR & 0103777) == 0100650) { /* FDD Div double by AC */ - if (!(fpu_unit.flags & UNIT_UP)) - continue; + if ((IR & 0103777) == 0100650) { /* FDD Div double by AC */ + if (!(fpu_unit.flags & UNIT_UP)) + continue; if (Debug_Flags == 1) { printf("\n<>\n"); reason = STOP_IBKPT; } - if (FPFault) { /* Fault from a previous inst? */ - FPFault = 0; - t = (GetMap(040) + 1) & AMASK; /* Yes: 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-1) & AMASK)); - if (C) PutMap(t, (GetMap(t) | 0100000)); - PutMap(040, t); - PC = indirect(GetMap(045)); /* JMP indirect to 45 */ - continue; - } - i = (IR >> 13) & 3; - j = (IR >> 11) & 3; - FPSR &= 0xFCFFFFFF; /* Z+N bits off */ - get_lf(&dfl, &FPAC[i]); /* Place in working registers */ - get_lf(&dfl2, &FPAC[j]); - k = div_lf(&dfl2, &dfl); /* Divide */ - if (k) { - switch (k) { - case 1: - FPSR |= 0x40000000; /* OVF bit on */ - break; - case 2: - FPSR |= 0x20000000; /* UNF bit on */ - break; - case 3: - FPSR |= 0x10000000; /* DVZ bit on */ - break; - } - } - store_lf(&dfl2, &FPAC[j]); /* put result in destination */ - if ((FPAC[j] & 0x00ffffffffffffff) == 0) - FPAC[j] = 0; - FPSR &= 0xFCFFFFFF; /* Z + N off */ - if (FPAC[j] == 0) - FPSR |= 0x02000000; /* Set Z */ - if (FPAC[j] & 0x8000000000000000) - FPSR |= 0x01000000; /* Set N */ - FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */ - FPSR |= ((PC - 1) & AMASK); + if (FPFault) { /* Fault from a previous inst? */ + FPFault = 0; + t = (GetMap(040) + 1) & AMASK; /* Yes: 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-1) & AMASK)); + if (C) PutMap(t, (GetMap(t) | 0100000)); + PutMap(040, t); + PC = indirect(GetMap(045)); /* JMP indirect to 45 */ + continue; + } + i = (IR >> 13) & 3; + j = (IR >> 11) & 3; + FPSR &= 0xFCFFFFFF; /* Z+N bits off */ + get_lf(&dfl, &FPAC[i]); /* Place in working registers */ + get_lf(&dfl2, &FPAC[j]); + k = div_lf(&dfl2, &dfl); /* Divide */ + if (k) { + switch (k) { + case 1: + FPSR |= 0x40000000; /* OVF bit on */ + break; + case 2: + FPSR |= 0x20000000; /* UNF bit on */ + break; + case 3: + FPSR |= 0x10000000; /* DVZ bit on */ + break; + } + } + store_lf(&dfl2, &FPAC[j]); /* put result in destination */ + if ((FPAC[j] & 0x00ffffffffffffff) == 0) + FPAC[j] = 0; + FPSR &= 0xFCFFFFFF; /* Z + N off */ + if (FPAC[j] == 0) + FPSR |= 0x02000000; /* Set Z */ + if (FPAC[j] & 0x8000000000000000) + FPSR |= 0x01000000; /* Set N */ + FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */ + FPSR |= ((PC - 1) & AMASK); continue; } - if ((IR & 0103777) == 0101650) { /* FDMD Div double by memory */ - if (!(fpu_unit.flags & UNIT_UP)) - continue; + if ((IR & 0103777) == 0101650) { /* FDMD Div double by memory */ + if (!(fpu_unit.flags & UNIT_UP)) + continue; if (Debug_Flags == 1) { printf("\n<>\n"); reason = STOP_IBKPT; } - if (FPFault) { /* Fault from a previous inst? */ - FPFault = 0; - t = (GetMap(040) + 1) & AMASK; /* Yes: 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-1) & AMASK)); - if (C) PutMap(t, (GetMap(t) | 0100000)); - PutMap(040, t); - PC = indirect(GetMap(045)); /* JMP indirect to 45 */ - continue; - } - j = (IR >> 11) & 3; + if (FPFault) { /* Fault from a previous inst? */ + FPFault = 0; + t = (GetMap(040) + 1) & AMASK; /* Yes: 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-1) & AMASK)); + if (C) PutMap(t, (GetMap(t) | 0100000)); + PutMap(040, t); + PC = indirect(GetMap(045)); /* JMP indirect to 45 */ + continue; + } + j = (IR >> 11) & 3; MA = effective(PC, (IR >> 13) & 3, GetMap(PC)); - tempfp = ((t_uint64)GetMap(MA) << 48); - tempfp |= ((t_uint64)GetMap(MA + 1) << 32); - tempfp |= ((t_uint64)GetMap(MA + 2) << 16); - tempfp |= ((t_uint64)GetMap(MA + 3)); - if ((tempfp & 0x00ffffffffffffff) == 0) - tempfp = 0; - FPSR &= 0xFCFFFFFF; /* Z+N bits off */ - get_lf(&dfl, &tempfp); /* Place in working registers */ - get_lf(&dfl2, &FPAC[j]); - k = div_lf(&dfl2, &dfl); /* Divide */ - if (k) { - switch (k) { - case 1: - FPSR |= 0x40000000; /* OVF bit on */ - break; - case 2: - FPSR |= 0x20000000; /* UNF bit on */ - break; - case 3: - FPSR |= 0x10000000; /* DVZ bit on */ - break; - } - } - store_lf(&dfl2, &FPAC[j]); /* put result in destination */ - if ((FPAC[j] & 0x00ffffffffffffff) == 0) - FPAC[j] = 0; - FPSR &= 0xFCFFFFFF; /* Z + N off */ - if (FPAC[j] == 0) - FPSR |= 0x02000000; /* Set Z */ - if (FPAC[j] & 0x8000000000000000) - FPSR |= 0x01000000; /* Set N */ - FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */ - FPSR |= ((PC - 1) & AMASK); + tempfp = ((t_uint64)GetMap(MA) << 48); + tempfp |= ((t_uint64)GetMap(MA + 1) << 32); + tempfp |= ((t_uint64)GetMap(MA + 2) << 16); + tempfp |= ((t_uint64)GetMap(MA + 3)); + if ((tempfp & 0x00ffffffffffffff) == 0) + tempfp = 0; + FPSR &= 0xFCFFFFFF; /* Z+N bits off */ + get_lf(&dfl, &tempfp); /* Place in working registers */ + get_lf(&dfl2, &FPAC[j]); + k = div_lf(&dfl2, &dfl); /* Divide */ + if (k) { + switch (k) { + case 1: + FPSR |= 0x40000000; /* OVF bit on */ + break; + case 2: + FPSR |= 0x20000000; /* UNF bit on */ + break; + case 3: + FPSR |= 0x10000000; /* DVZ bit on */ + break; + } + } + store_lf(&dfl2, &FPAC[j]); /* put result in destination */ + if ((FPAC[j] & 0x00ffffffffffffff) == 0) + FPAC[j] = 0; + FPSR &= 0xFCFFFFFF; /* Z + N off */ + if (FPAC[j] == 0) + FPSR |= 0x02000000; /* Set Z */ + if (FPAC[j] & 0x8000000000000000) + FPSR |= 0x01000000; /* Set N */ + FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */ + FPSR |= ((PC - 1) & AMASK); PC = (PC + 1) & AMASK; continue; } - if ((IR & 0163777) == 0163050) { /* FNEG Negate */ - if (!(fpu_unit.flags & UNIT_UP)) - continue; + if ((IR & 0163777) == 0163050) { /* FNEG Negate */ + if (!(fpu_unit.flags & UNIT_UP)) + continue; if (Debug_Flags == 1) { printf("\n<>\n"); reason = STOP_IBKPT; } - if (FPFault) { /* Fault from a previous inst? */ - FPFault = 0; - t = (GetMap(040) + 1) & AMASK; /* Yes: 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-1) & AMASK)); - if (C) PutMap(t, (GetMap(t) | 0100000)); - PutMap(040, t); - PC = indirect(GetMap(045)); /* JMP indirect to 45 */ - continue; - } - j = (IR >> 11) & 3; - FPSR &= 0xFCFFFFFF; /* Z+N bits off */ - get_lf(&dfl, &FPAC[j]); - dfl.sign = ! (dfl.sign); /* invert sign */ - store_lf(&dfl, &FPAC[j]); /* put result in destination */ - if ((FPAC[j] & 0x00ffffffffffffff) == 0) - FPAC[j] = 0; - FPSR &= 0xFCFFFFFF; /* Z + N off */ - if (FPAC[j] == 0) - FPSR |= 0x02000000; /* Set Z */ - if (FPAC[j] & 0x8000000000000000) - FPSR |= 0x01000000; /* Set N */ - FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */ - FPSR |= ((PC - 1) & AMASK); + if (FPFault) { /* Fault from a previous inst? */ + FPFault = 0; + t = (GetMap(040) + 1) & AMASK; /* Yes: 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-1) & AMASK)); + if (C) PutMap(t, (GetMap(t) | 0100000)); + PutMap(040, t); + PC = indirect(GetMap(045)); /* JMP indirect to 45 */ + continue; + } + j = (IR >> 11) & 3; + FPSR &= 0xFCFFFFFF; /* Z+N bits off */ + get_lf(&dfl, &FPAC[j]); + dfl.sign = ! (dfl.sign); /* invert sign */ + store_lf(&dfl, &FPAC[j]); /* put result in destination */ + if ((FPAC[j] & 0x00ffffffffffffff) == 0) + FPAC[j] = 0; + FPSR &= 0xFCFFFFFF; /* Z + N off */ + if (FPAC[j] == 0) + FPSR |= 0x02000000; /* Set Z */ + if (FPAC[j] & 0x8000000000000000) + FPSR |= 0x01000000; /* Set N */ + FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */ + FPSR |= ((PC - 1) & AMASK); continue; } - if ((IR & 0163777) == 0143050) { /* FAB Absolute Value*/ - if (!(fpu_unit.flags & UNIT_UP)) - continue; + if ((IR & 0163777) == 0143050) { /* FAB Absolute Value*/ + if (!(fpu_unit.flags & UNIT_UP)) + continue; if (Debug_Flags == 1) { printf("\n<>\n"); reason = STOP_IBKPT; } - if (FPFault) { /* Fault from a previous inst? */ - FPFault = 0; - t = (GetMap(040) + 1) & AMASK; /* Yes: 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-1) & AMASK)); - if (C) PutMap(t, (GetMap(t) | 0100000)); - PutMap(040, t); - PC = indirect(GetMap(045)); /* JMP indirect to 45 */ - continue; - } - j = (IR >> 11) & 3; - FPSR &= 0xFCFFFFFF; /* Z+N bits off */ - get_lf(&dfl, &FPAC[j]); - dfl.sign = 0; /* Force sign positive */ - store_lf(&dfl, &FPAC[j]); /* put result in destination */ - if ((FPAC[j] & 0x00ffffffffffffff) == 0) - FPAC[j] = 0; - FPSR &= 0xFCFFFFFF; /* Z + N off */ - if (FPAC[j] == 0) - FPSR |= 0x02000000; /* Set Z */ - if (FPAC[j] & 0x8000000000000000) - FPSR |= 0x01000000; /* Set N */ - FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */ - FPSR |= ((PC - 1) & AMASK); + if (FPFault) { /* Fault from a previous inst? */ + FPFault = 0; + t = (GetMap(040) + 1) & AMASK; /* Yes: 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-1) & AMASK)); + if (C) PutMap(t, (GetMap(t) | 0100000)); + PutMap(040, t); + PC = indirect(GetMap(045)); /* JMP indirect to 45 */ + continue; + } + j = (IR >> 11) & 3; + FPSR &= 0xFCFFFFFF; /* Z+N bits off */ + get_lf(&dfl, &FPAC[j]); + dfl.sign = 0; /* Force sign positive */ + store_lf(&dfl, &FPAC[j]); /* put result in destination */ + if ((FPAC[j] & 0x00ffffffffffffff) == 0) + FPAC[j] = 0; + FPSR &= 0xFCFFFFFF; /* Z + N off */ + if (FPAC[j] == 0) + FPSR |= 0x02000000; /* Set Z */ + if (FPAC[j] & 0x8000000000000000) + FPSR |= 0x01000000; /* Set N */ + FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */ + FPSR |= ((PC - 1) & AMASK); continue; } - if ((IR & 0163777) == 0103050) { /* FNOM Normalize*/ - if (!(fpu_unit.flags & UNIT_UP)) - continue; + if ((IR & 0163777) == 0103050) { /* FNOM Normalize*/ + if (!(fpu_unit.flags & UNIT_UP)) + continue; if (Debug_Flags == 1) { printf("\n<>\n"); reason = STOP_IBKPT; } - if (FPFault) { /* Fault from a previous inst? */ - FPFault = 0; - t = (GetMap(040) + 1) & AMASK; /* Yes: 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-1) & AMASK)); - if (C) PutMap(t, (GetMap(t) | 0100000)); - PutMap(040, t); - PC = indirect(GetMap(045)); /* JMP indirect to 45 */ - continue; - } - j = (IR >> 11) & 3; - FPSR &= 0xFCFFFFFF; /* Z+N bits off */ - get_lf(&dfl, &FPAC[j]); - k = normal_lf(&dfl); /* Normalize */ - if (k == 2) /* Underflow ? */ - FPSR |= 0x20000000; /* Set underflow on */ - store_lf(&dfl, &FPAC[j]); /* put result in destination */ - if ((FPAC[j] & 0x00ffffffffffffff) == 0) - FPAC[j] = 0; - FPSR &= 0xFCFFFFFF; /* Z + N off */ - if (FPAC[j] == 0) - FPSR |= 0x02000000; /* Set Z */ - if (FPAC[j] & 0x8000000000000000) - FPSR |= 0x01000000; /* Set N */ - FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */ - FPSR |= ((PC - 1) & AMASK); + if (FPFault) { /* Fault from a previous inst? */ + FPFault = 0; + t = (GetMap(040) + 1) & AMASK; /* Yes: 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-1) & AMASK)); + if (C) PutMap(t, (GetMap(t) | 0100000)); + PutMap(040, t); + PC = indirect(GetMap(045)); /* JMP indirect to 45 */ + continue; + } + j = (IR >> 11) & 3; + FPSR &= 0xFCFFFFFF; /* Z+N bits off */ + get_lf(&dfl, &FPAC[j]); + k = normal_lf(&dfl); /* Normalize */ + if (k == 2) /* Underflow ? */ + FPSR |= 0x20000000; /* Set underflow on */ + store_lf(&dfl, &FPAC[j]); /* put result in destination */ + if ((FPAC[j] & 0x00ffffffffffffff) == 0) + FPAC[j] = 0; + FPSR &= 0xFCFFFFFF; /* Z + N off */ + if (FPAC[j] == 0) + FPSR |= 0x02000000; /* Set Z */ + if (FPAC[j] & 0x8000000000000000) + FPSR |= 0x01000000; /* Set N */ + FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */ + FPSR |= ((PC - 1) & AMASK); continue; } - if ((IR & 0163777) == 0123050) { /* FRH Read High Word */ - if (!(fpu_unit.flags & UNIT_UP)) - continue; + if ((IR & 0163777) == 0123050) { /* FRH Read High Word */ + if (!(fpu_unit.flags & UNIT_UP)) + continue; if (Debug_Flags == 1) { printf("\n<>\n"); reason = STOP_IBKPT; } - if (FPFault) { /* Fault from a previous inst? */ - FPFault = 0; - t = (GetMap(040) + 1) & AMASK; /* Yes: 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-1) & AMASK)); - if (C) PutMap(t, (GetMap(t) | 0100000)); - PutMap(040, t); - PC = indirect(GetMap(045)); /* JMP indirect to 45 */ - continue; - } - j = (IR >> 11) & 3; - AC[0] = (int32)(FPAC[j] >> 48) & 0xFFFF; /* No cond bits set, always to AC0 */ - FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */ - FPSR |= ((PC - 1) & AMASK); + if (FPFault) { /* Fault from a previous inst? */ + FPFault = 0; + t = (GetMap(040) + 1) & AMASK; /* Yes: 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-1) & AMASK)); + if (C) PutMap(t, (GetMap(t) | 0100000)); + PutMap(040, t); + PC = indirect(GetMap(045)); /* JMP indirect to 45 */ + continue; + } + j = (IR >> 11) & 3; + AC[0] = (int32)(FPAC[j] >> 48) & 0xFFFF; /* No cond bits set, always to AC0 */ + FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */ + FPSR |= ((PC - 1) & AMASK); continue; } - if ((IR & 0163777) == 0123150) { /* FEXP Load Exponent */ - if (!(fpu_unit.flags & UNIT_UP)) - continue; + if ((IR & 0163777) == 0123150) { /* FEXP Load Exponent */ + if (!(fpu_unit.flags & UNIT_UP)) + continue; if (Debug_Flags == 1) { printf("\n<>\n"); reason = STOP_IBKPT; - continue; + continue; } - if (FPFault) { /* Fault from a previous inst? */ - FPFault = 0; - t = (GetMap(040) + 1) & AMASK; /* Yes: 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-1) & AMASK)); - if (C) PutMap(t, (GetMap(t) | 0100000)); - PutMap(040, t); - PC = indirect(GetMap(045)); /* JMP indirect to 45 */ - continue; - } - j = (IR >> 11) & 3; - i = (AC[0] >> 8) & 0x007F; - FPAC[j] &= 0x80FFFFFFFFFFFFFF; /* clear exponent */ - FPAC[j] |= ((t_int64) i << 56); - if ((FPAC[j] & 0x00ffffffffffffff) == 0) - FPAC[j] = 0; - if (FPAC[j] == 0) - FPSR |= 0x02000000; /* Set Z */ - if (FPAC[j] & 0x8000000000000000) - FPSR |= 0x01000000; /* Set N */ - FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */ - FPSR |= ((PC - 1) & AMASK); + if (FPFault) { /* Fault from a previous inst? */ + FPFault = 0; + t = (GetMap(040) + 1) & AMASK; /* Yes: 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-1) & AMASK)); + if (C) PutMap(t, (GetMap(t) | 0100000)); + PutMap(040, t); + PC = indirect(GetMap(045)); /* JMP indirect to 45 */ + continue; + } + j = (IR >> 11) & 3; + i = (AC[0] >> 8) & 0x007F; + FPAC[j] &= 0x80FFFFFFFFFFFFFF; /* clear exponent */ + FPAC[j] |= ((t_int64) i << 56); + if ((FPAC[j] & 0x00ffffffffffffff) == 0) + FPAC[j] = 0; + if (FPAC[j] == 0) + FPSR |= 0x02000000; /* Set Z */ + if (FPAC[j] & 0x8000000000000000) + FPSR |= 0x01000000; /* Set N */ + FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */ + FPSR |= ((PC - 1) & AMASK); continue; } - if ((IR & 0103777) == 0103450) { /* FCMP FP Compare */ - if (!(fpu_unit.flags & UNIT_UP)) /* (Subtract double AC without storing result) */ - continue; + if ((IR & 0103777) == 0103450) { /* FCMP FP Compare */ + if (!(fpu_unit.flags & UNIT_UP)) /* (Subtract double AC without storing result) */ + continue; if (Debug_Flags == 1) { printf("\n<>\n"); reason = STOP_IBKPT; } - if (FPFault) { /* Fault from a previous inst? */ - FPFault = 0; - t = (GetMap(040) + 1) & AMASK; /* Yes: 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-1) & AMASK)); - if (C) PutMap(t, (GetMap(t) | 0100000)); - PutMap(040, t); - PC = indirect(GetMap(045)); /* JMP indirect to 45 */ - continue; - } - i = (IR >> 13) & 3; - j = (IR >> 11) & 3; - FPSR &= 0xFCFFFFFF; /* Z+N bits off */ - get_lf(&dfl, &FPAC[i]); /* Place in working registers */ - get_lf(&dfl2, &FPAC[j]); - dfl.sign = ! (dfl.sign); /* invert sign of 2nd operand */ - k = add_lf(&dfl2, &dfl, 1); /* Add the two */ - if (k) { - switch (k) { - case 1: - FPSR |= 0x40000000; /* OVF bit on */ - break; - case 2: - FPSR |= 0x20000000; /* UNF bit on */ - break; - } - } - if ((FPAC[j] & 0x00ffffffffffffff) == 0) - FPAC[j] = 0; - FPSR &= 0xFCFFFFFF; /* Z + N off */ - if (FPAC[j] == 0) - FPSR |= 0x02000000; /* Set Z */ - if (FPAC[j] & 0x8000000000000000) - FPSR |= 0x01000000; /* Set N */ - FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */ - FPSR |= ((PC - 1) & AMASK); + if (FPFault) { /* Fault from a previous inst? */ + FPFault = 0; + t = (GetMap(040) + 1) & AMASK; /* Yes: 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-1) & AMASK)); + if (C) PutMap(t, (GetMap(t) | 0100000)); + PutMap(040, t); + PC = indirect(GetMap(045)); /* JMP indirect to 45 */ + continue; + } + i = (IR >> 13) & 3; + j = (IR >> 11) & 3; + FPSR &= 0xFCFFFFFF; /* Z+N bits off */ + get_lf(&dfl, &FPAC[i]); /* Place in working registers */ + get_lf(&dfl2, &FPAC[j]); + dfl.sign = ! (dfl.sign); /* invert sign of 2nd operand */ + k = add_lf(&dfl2, &dfl, 1); /* Add the two */ + if (k) { + switch (k) { + case 1: + FPSR |= 0x40000000; /* OVF bit on */ + break; + case 2: + FPSR |= 0x20000000; /* UNF bit on */ + break; + } + } + if ((FPAC[j] & 0x00ffffffffffffff) == 0) + FPAC[j] = 0; + FPSR &= 0xFCFFFFFF; /* Z + N off */ + if (FPAC[j] == 0) + FPSR |= 0x02000000; /* Set Z */ + if (FPAC[j] & 0x8000000000000000) + FPSR |= 0x01000000; /* Set N */ + FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */ + FPSR |= ((PC - 1) & AMASK); continue; } - if (IR == 0163350) { /* FPSH Push State */ - if (!(fpu_unit.flags & UNIT_UP)) - continue; + if (IR == 0163350) { /* FPSH Push State */ + if (!(fpu_unit.flags & UNIT_UP)) + continue; if (Debug_Flags == 2) { printf("\n<>\n"); reason = STOP_IBKPT; } - /* Note: FPSH and FPOP do not trap on error */ - t = (GetMap(040) + 1) & AMASK; /* Get Stack Pointer */ - PutMap(t, ((FPSR >> 16) & 0xFFFF)); - t++; - PutMap(t, (FPSR & 0xFFFF)); - t++; - PutMap(t, (int16)((FPAC[0] >> 48) & 0xFFFF)); - t++; - PutMap(t, (int16)((FPAC[0] >> 32) & 0xFFFF)); - t++; - PutMap(t, (int16)((FPAC[0] >> 16) & 0xFFFF)); - t++; - PutMap(t, (int16)(FPAC[0] & 0xFFFF)); - t++; - PutMap(t, (int16)((FPAC[1] >> 48) & 0xFFFF)); - t++; - PutMap(t, (int16)((FPAC[1] >> 32) & 0xFFFF)); - t++; - PutMap(t, (int16)((FPAC[1] >> 16) & 0xFFFF)); - t++; - PutMap(t, (int16)(FPAC[1] & 0xFFFF)); - t++; - PutMap(t, (int16)((FPAC[2] >> 48) & 0xFFFF)); - t++; - PutMap(t, (int16)((FPAC[2] >> 32) & 0xFFFF)); - t++; - PutMap(t, (int16)((FPAC[2] >> 16) & 0xFFFF)); - t++; - PutMap(t, (int16)(FPAC[2] & 0xFFFF)); - t++; - PutMap(t, (int16)((FPAC[3] >> 48) & 0xFFFF)); - t++; - PutMap(t, (int16)((FPAC[3] >> 32) & 0xFFFF)); - t++; - PutMap(t, (int16)((FPAC[3] >> 16) & 0xFFFF)); - t++; - PutMap(t, (int16)(FPAC[3] & 0xFFFF)); - PutMap(040, t); /* Update Stack Pointer */ + /* Note: FPSH and FPOP do not trap on error */ + t = (GetMap(040) + 1) & AMASK; /* Get Stack Pointer */ + PutMap(t, ((FPSR >> 16) & 0xFFFF)); + t++; + PutMap(t, (FPSR & 0xFFFF)); + t++; + PutMap(t, (int16)((FPAC[0] >> 48) & 0xFFFF)); + t++; + PutMap(t, (int16)((FPAC[0] >> 32) & 0xFFFF)); + t++; + PutMap(t, (int16)((FPAC[0] >> 16) & 0xFFFF)); + t++; + PutMap(t, (int16)(FPAC[0] & 0xFFFF)); + t++; + PutMap(t, (int16)((FPAC[1] >> 48) & 0xFFFF)); + t++; + PutMap(t, (int16)((FPAC[1] >> 32) & 0xFFFF)); + t++; + PutMap(t, (int16)((FPAC[1] >> 16) & 0xFFFF)); + t++; + PutMap(t, (int16)(FPAC[1] & 0xFFFF)); + t++; + PutMap(t, (int16)((FPAC[2] >> 48) & 0xFFFF)); + t++; + PutMap(t, (int16)((FPAC[2] >> 32) & 0xFFFF)); + t++; + PutMap(t, (int16)((FPAC[2] >> 16) & 0xFFFF)); + t++; + PutMap(t, (int16)(FPAC[2] & 0xFFFF)); + t++; + PutMap(t, (int16)((FPAC[3] >> 48) & 0xFFFF)); + t++; + PutMap(t, (int16)((FPAC[3] >> 32) & 0xFFFF)); + t++; + PutMap(t, (int16)((FPAC[3] >> 16) & 0xFFFF)); + t++; + PutMap(t, (int16)(FPAC[3] & 0xFFFF)); + PutMap(040, t); /* Update Stack Pointer */ continue; } - if (IR == 0167350) { /* FPOP Pop State */ - if (!(fpu_unit.flags & UNIT_UP)) - continue; + if (IR == 0167350) { /* FPOP Pop State */ + if (!(fpu_unit.flags & UNIT_UP)) + continue; if (Debug_Flags == 2) { printf("\n<>\n"); reason = STOP_IBKPT; } - /* Note: FPSH and FPOP do not trap on error */ - t = GetMap(040) & AMASK; /* Get Stack Pointer */ - FPAC[3] = ((t_uint64)GetMap(t) & 0xFFFF); - t--; - FPAC[3] |= (((t_uint64)GetMap(t) << 16) & 0xFFFF0000); - t--; - FPAC[3] |= (((t_uint64)GetMap(t) << 32) & 0xFFFF00000000); - t--; - FPAC[3] |= (((t_uint64)GetMap(t) << 48) & 0xFFFF000000000000); - t--; - FPAC[2] = ((t_uint64)GetMap(t) & 0xFFFF); - t--; - FPAC[2] |= (((t_uint64)GetMap(t) << 16) & 0xFFFF0000); - t--; - FPAC[2] |= (((t_uint64)GetMap(t) << 32) & 0xFFFF00000000); - t--; - FPAC[2] |= (((t_uint64)GetMap(t) << 48) & 0xFFFF000000000000); - t--; - FPAC[1] = ((t_uint64)GetMap(t) & 0xFFFF); - t--; - FPAC[1] |= (((t_uint64)GetMap(t) << 16) & 0xFFFF0000); - t--; - FPAC[1] |= (((t_uint64)GetMap(t) << 32) & 0xFFFF00000000); - t--; - FPAC[1] |= (((t_uint64)GetMap(t) << 48) & 0xFFFF000000000000); - t--; - FPAC[0] = ((t_uint64)GetMap(t) & 0xFFFF); - t--; - FPAC[0] |= (((t_uint64)GetMap(t) << 16) & 0xFFFF0000); - t--; - FPAC[0] |= (((t_uint64)GetMap(t) << 32) & 0xFFFF00000000); - t--; - FPAC[0] |= (((t_uint64)GetMap(t) << 48) & 0xFFFF000000000000); - t--; - FPSR = (GetMap(t) & 0xFFFF); - t--; - FPSR |= ((GetMap(t) << 16) & 0xFFFF0000); - t--; - PutMap(040, t); /* Update Stack Pointer */ + /* Note: FPSH and FPOP do not trap on error */ + t = GetMap(040) & AMASK; /* Get Stack Pointer */ + FPAC[3] = ((t_uint64)GetMap(t) & 0xFFFF); + t--; + FPAC[3] |= (((t_uint64)GetMap(t) << 16) & 0xFFFF0000); + t--; + FPAC[3] |= (((t_uint64)GetMap(t) << 32) & 0xFFFF00000000); + t--; + FPAC[3] |= (((t_uint64)GetMap(t) << 48) & 0xFFFF000000000000); + t--; + FPAC[2] = ((t_uint64)GetMap(t) & 0xFFFF); + t--; + FPAC[2] |= (((t_uint64)GetMap(t) << 16) & 0xFFFF0000); + t--; + FPAC[2] |= (((t_uint64)GetMap(t) << 32) & 0xFFFF00000000); + t--; + FPAC[2] |= (((t_uint64)GetMap(t) << 48) & 0xFFFF000000000000); + t--; + FPAC[1] = ((t_uint64)GetMap(t) & 0xFFFF); + t--; + FPAC[1] |= (((t_uint64)GetMap(t) << 16) & 0xFFFF0000); + t--; + FPAC[1] |= (((t_uint64)GetMap(t) << 32) & 0xFFFF00000000); + t--; + FPAC[1] |= (((t_uint64)GetMap(t) << 48) & 0xFFFF000000000000); + t--; + FPAC[0] = ((t_uint64)GetMap(t) & 0xFFFF); + t--; + FPAC[0] |= (((t_uint64)GetMap(t) << 16) & 0xFFFF0000); + t--; + FPAC[0] |= (((t_uint64)GetMap(t) << 32) & 0xFFFF00000000); + t--; + FPAC[0] |= (((t_uint64)GetMap(t) << 48) & 0xFFFF000000000000); + t--; + FPSR = (GetMap(t) & 0xFFFF); + t--; + FPSR |= ((GetMap(t) << 16) & 0xFFFF0000); + t--; + PutMap(040, t); /* Update Stack Pointer */ continue; } - if ((IR & 0163777) == 0163150) { /* FHLV Halve */ - if (!(fpu_unit.flags & UNIT_UP)) - continue; + if ((IR & 0163777) == 0163150) { /* FHLV Halve */ + if (!(fpu_unit.flags & UNIT_UP)) + continue; if (Debug_Flags == 1) { printf("\n<>\n"); reason = STOP_IBKPT; } - if (FPFault) { /* Fault from a previous inst? */ - FPFault = 0; - t = (GetMap(040) + 1) & AMASK; /* Yes: 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-1) & AMASK)); - if (C) PutMap(t, (GetMap(t) | 0100000)); - PutMap(040, t); - PC = indirect(GetMap(045)); /* JMP indirect to 45 */ - continue; - } - j = (IR >> 11) & 3; - FPSR &= 0xFCFFFFFF; /* Z+N bits off */ - get_lf(&dfl, &FPAC[j]); - dfl.long_fract = dfl.long_fract >> 1; /* Shift right one bit */ - normal_lf(&dfl); /* Normalize */ - store_lf(&dfl, &FPAC[j]); /* put result in destination */ - if ((FPAC[j] & 0x00ffffffffffffff) == 0) - FPAC[j] = 0; - FPSR &= 0xFCFFFFFF; /* Z + N off */ - if (FPAC[j] == 0) - FPSR |= 0x02000000; /* Set Z */ - if (FPAC[j] & 0x8000000000000000) - FPSR |= 0x01000000; /* Set N */ - FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */ - FPSR |= ((PC - 1) & AMASK); + if (FPFault) { /* Fault from a previous inst? */ + FPFault = 0; + t = (GetMap(040) + 1) & AMASK; /* Yes: 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-1) & AMASK)); + if (C) PutMap(t, (GetMap(t) | 0100000)); + PutMap(040, t); + PC = indirect(GetMap(045)); /* JMP indirect to 45 */ + continue; + } + j = (IR >> 11) & 3; + FPSR &= 0xFCFFFFFF; /* Z+N bits off */ + get_lf(&dfl, &FPAC[j]); + dfl.long_fract = dfl.long_fract >> 1; /* Shift right one bit */ + normal_lf(&dfl); /* Normalize */ + store_lf(&dfl, &FPAC[j]); /* put result in destination */ + if ((FPAC[j] & 0x00ffffffffffffff) == 0) + FPAC[j] = 0; + FPSR &= 0xFCFFFFFF; /* Z + N off */ + if (FPAC[j] == 0) + FPSR |= 0x02000000; /* Set Z */ + if (FPAC[j] & 0x8000000000000000) + FPSR |= 0x01000000; /* Set N */ + FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */ + FPSR |= ((PC - 1) & AMASK); continue; } - if ((IR & 0163777) == 0103150) { /* FSCAL Scale */ - if (!(fpu_unit.flags & UNIT_UP)) - continue; + if ((IR & 0163777) == 0103150) { /* FSCAL Scale */ + if (!(fpu_unit.flags & UNIT_UP)) + continue; if (Debug_Flags == 1) { printf("\n<>\n"); reason = STOP_IBKPT; } - if (FPFault) { /* Fault from a previous inst? */ - FPFault = 0; - t = (GetMap(040) + 1) & AMASK; /* Yes: 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-1) & AMASK)); - if (C) PutMap(t, (GetMap(t) | 0100000)); - PutMap(040, t); - PC = indirect(GetMap(045)); /* JMP indirect to 45 */ - continue; - } - i = (IR >> 11) & 3; - FPSR &= 0xFCFFFFFF; /* Z+N bits off */ - j = (AC[0] >> 8) & 0x7F; /* expo of AC0 */ - k = (int32)(FPAC[i] >> 56) & 0x7F; /* expo of FPAC */ - tempfp = FPAC[i] & 0x8000000000000000; /* save sign */ - t = j - k; - if (t > 0) { /* Positive shift */ - FPAC[i] &= 0x00FFFFFFFFFFFFFF; - FPAC[i] = FPAC[i] >> (t * 4); - FPAC[i] &= 0x00FFFFFFFFFFFFFF; /* AC0 expo becomes expo */ - holdfp = j; - FPAC[i] |= (holdfp << 56); - } - if (t < 0) { /* Negative shift */ - FPAC[i] &= 0x00FFFFFFFFFFFFFF; - FPAC[i] = FPAC[i] << ((0-t) * 4); - FPSR |= 0x08000000; /* MOF bit on */ - FPAC[i] &= 0x00FFFFFFFFFFFFFF; /* AC0 expo becomes expo */ - holdfp = j; - FPAC[i] |= (holdfp << 56); - } - if ((FPAC[i] & 0x00FFFFFFFFFFFFFF) != 0) - FPAC[i] |= tempfp; /* restore sign */ - if ((FPAC[i] & 0x80FFFFFFFFFFFFFF) == 0) { - FPAC[i] = 0; - FPSR |= 0x02000000; /* Set Z */ - } - if (FPAC[i] & 0x8000000000000000) - FPSR |= 0x01000000; /* Set N */ - FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */ - FPSR |= ((PC - 1) & AMASK); + if (FPFault) { /* Fault from a previous inst? */ + FPFault = 0; + t = (GetMap(040) + 1) & AMASK; /* Yes: 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-1) & AMASK)); + if (C) PutMap(t, (GetMap(t) | 0100000)); + PutMap(040, t); + PC = indirect(GetMap(045)); /* JMP indirect to 45 */ + continue; + } + i = (IR >> 11) & 3; + FPSR &= 0xFCFFFFFF; /* Z+N bits off */ + j = (AC[0] >> 8) & 0x7F; /* expo of AC0 */ + k = (int32)(FPAC[i] >> 56) & 0x7F; /* expo of FPAC */ + tempfp = FPAC[i] & 0x8000000000000000; /* save sign */ + t = j - k; + if (t > 0) { /* Positive shift */ + FPAC[i] &= 0x00FFFFFFFFFFFFFF; + FPAC[i] = FPAC[i] >> (t * 4); + FPAC[i] &= 0x00FFFFFFFFFFFFFF; /* AC0 expo becomes expo */ + holdfp = j; + FPAC[i] |= (holdfp << 56); + } + if (t < 0) { /* Negative shift */ + FPAC[i] &= 0x00FFFFFFFFFFFFFF; + FPAC[i] = FPAC[i] << ((0-t) * 4); + FPSR |= 0x08000000; /* MOF bit on */ + FPAC[i] &= 0x00FFFFFFFFFFFFFF; /* AC0 expo becomes expo */ + holdfp = j; + FPAC[i] |= (holdfp << 56); + } + if ((FPAC[i] & 0x00FFFFFFFFFFFFFF) != 0) + FPAC[i] |= tempfp; /* restore sign */ + if ((FPAC[i] & 0x80FFFFFFFFFFFFFF) == 0) { + FPAC[i] = 0; + FPSR |= 0x02000000; /* Set Z */ + } + if (FPAC[i] & 0x8000000000000000) + FPSR |= 0x01000000; /* Set N */ + FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */ + FPSR |= ((PC - 1) & AMASK); continue; } - if (IR == 0153350) { /* FCLE Clear Errors */ - if (!(fpu_unit.flags & UNIT_UP)) - continue; + if (IR == 0153350) { /* FCLE Clear Errors */ + if (!(fpu_unit.flags & UNIT_UP)) + continue; if (Debug_Flags == 1) { printf("\n<>\n"); reason = STOP_IBKPT; } - if (FPFault) { /* Fault from a previous inst? */ - FPFault = 0; - t = (GetMap(040) + 1) & AMASK; /* Yes: 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-1) & AMASK)); - if (C) PutMap(t, (GetMap(t) | 0100000)); - PutMap(040, t); - PC = indirect(GetMap(045)); /* JMP indirect to 45 */ - continue; - } - FPSR &= 0x07FFFFFF; /* set off all error bits */ - FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */ - FPSR |= ((PC - 1) & AMASK); + if (FPFault) { /* Fault from a previous inst? */ + FPFault = 0; + t = (GetMap(040) + 1) & AMASK; /* Yes: 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-1) & AMASK)); + if (C) PutMap(t, (GetMap(t) | 0100000)); + PutMap(040, t); + PC = indirect(GetMap(045)); /* JMP indirect to 45 */ + continue; + } + FPSR &= 0x07FFFFFF; /* set off all error bits */ + FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */ + FPSR |= ((PC - 1) & AMASK); continue; } - if (IR == 0103250) { /* FNS No Skip */ - if (!(fpu_unit.flags & UNIT_UP)) - continue; + if (IR == 0103250) { /* FNS No Skip */ + if (!(fpu_unit.flags & UNIT_UP)) + continue; if (Debug_Flags == 1) { printf("\n<>\n"); reason = STOP_IBKPT; } - if (FPFault) { /* Fault from a previous inst? */ - FPFault = 0; - t = (GetMap(040) + 1) & AMASK; /* Yes: 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-1) & AMASK)); - if (C) PutMap(t, (GetMap(t) | 0100000)); - PutMap(040, t); - PC = indirect(GetMap(045)); /* JMP indirect to 45 */ - continue; - } - FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */ - FPSR |= ((PC - 1) & AMASK); + if (FPFault) { /* Fault from a previous inst? */ + FPFault = 0; + t = (GetMap(040) + 1) & AMASK; /* Yes: 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-1) & AMASK)); + if (C) PutMap(t, (GetMap(t) | 0100000)); + PutMap(040, t); + PC = indirect(GetMap(045)); /* JMP indirect to 45 */ + continue; + } + FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */ + FPSR |= ((PC - 1) & AMASK); continue; } - if (IR == 0107250) { /* FSA Always Skip */ - if (!(fpu_unit.flags & UNIT_UP)) - continue; + if (IR == 0107250) { /* FSA Always Skip */ + if (!(fpu_unit.flags & UNIT_UP)) + continue; if (Debug_Flags == 2) { printf("\n<>\n"); reason = STOP_IBKPT; } - if (FPFault) { /* Fault from a previous inst? */ - FPFault = 0; - t = (GetMap(040) + 1) & AMASK; /* Yes: 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-1) & AMASK)); - if (C) PutMap(t, (GetMap(t) | 0100000)); - PutMap(040, t); - PC = indirect(GetMap(045)); /* JMP indirect to 45 */ - continue; - } - FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */ - FPSR |= ((PC - 1) & AMASK); + if (FPFault) { /* Fault from a previous inst? */ + FPFault = 0; + t = (GetMap(040) + 1) & AMASK; /* Yes: 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-1) & AMASK)); + if (C) PutMap(t, (GetMap(t) | 0100000)); + PutMap(040, t); + PC = indirect(GetMap(045)); /* JMP indirect to 45 */ + continue; + } + FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */ + FPSR |= ((PC - 1) & AMASK); PC = (PC + 1) & AMASK; continue; } - if (IR == 0137250) { /* FSGT */ - if (!(fpu_unit.flags & UNIT_UP)) - continue; + if (IR == 0137250) { /* FSGT */ + if (!(fpu_unit.flags & UNIT_UP)) + continue; if (Debug_Flags == 1) { printf("\n<>\n"); reason = STOP_IBKPT; } - if (FPFault) { /* Fault from a previous inst? */ - FPFault = 0; - t = (GetMap(040) + 1) & AMASK; /* Yes: 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-1) & AMASK)); - if (C) PutMap(t, (GetMap(t) | 0100000)); - PutMap(040, t); - PC = indirect(GetMap(045)); /* JMP indirect to 45 */ - continue; - } - FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */ - FPSR |= ((PC - 1) & AMASK); - if (!(FPSR & 0x03000000)) /* Z & N both 0? */ - PC = (PC + 1) & AMASK; /* yep: skip */ + if (FPFault) { /* Fault from a previous inst? */ + FPFault = 0; + t = (GetMap(040) + 1) & AMASK; /* Yes: 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-1) & AMASK)); + if (C) PutMap(t, (GetMap(t) | 0100000)); + PutMap(040, t); + PC = indirect(GetMap(045)); /* JMP indirect to 45 */ + continue; + } + FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */ + FPSR |= ((PC - 1) & AMASK); + if (!(FPSR & 0x03000000)) /* Z & N both 0? */ + PC = (PC + 1) & AMASK; /* yep: skip */ continue; } - if (IR == 0123250) { /* FSLT */ - if (!(fpu_unit.flags & UNIT_UP)) - continue; + if (IR == 0123250) { /* FSLT */ + if (!(fpu_unit.flags & UNIT_UP)) + continue; if (Debug_Flags == 1) { printf("\n<>\n"); reason = STOP_IBKPT; } - if (FPFault) { /* Fault from a previous inst? */ - FPFault = 0; - t = (GetMap(040) + 1) & AMASK; /* Yes: 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-1) & AMASK)); - if (C) PutMap(t, (GetMap(t) | 0100000)); - PutMap(040, t); - PC = indirect(GetMap(045)); /* JMP indirect to 45 */ - continue; - } - FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */ - FPSR |= ((PC - 1) & AMASK); - if (FPSR & 0x01000000) /* N is on? */ - PC = (PC + 1) & AMASK; /* yep: skip */ + if (FPFault) { /* Fault from a previous inst? */ + FPFault = 0; + t = (GetMap(040) + 1) & AMASK; /* Yes: 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-1) & AMASK)); + if (C) PutMap(t, (GetMap(t) | 0100000)); + PutMap(040, t); + PC = indirect(GetMap(045)); /* JMP indirect to 45 */ + continue; + } + FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */ + FPSR |= ((PC - 1) & AMASK); + if (FPSR & 0x01000000) /* N is on? */ + PC = (PC + 1) & AMASK; /* yep: skip */ continue; } - if (IR == 0113250) { /* FSEQ */ - if (!(fpu_unit.flags & UNIT_UP)) - continue; + if (IR == 0113250) { /* FSEQ */ + if (!(fpu_unit.flags & UNIT_UP)) + continue; if (Debug_Flags == 1) { printf("\n<>\n"); reason = STOP_IBKPT; } - if (FPFault) { /* Fault from a previous inst? */ - FPFault = 0; - t = (GetMap(040) + 1) & AMASK; /* Yes: 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-1) & AMASK)); - if (C) PutMap(t, (GetMap(t) | 0100000)); - PutMap(040, t); - PC = indirect(GetMap(045)); /* JMP indirect to 45 */ - continue; - } - FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */ - FPSR |= ((PC - 1) & AMASK); - if (FPSR & 0x02000000) /* Z is on? */ - PC = (PC + 1) & AMASK; /* yep: skip */ + if (FPFault) { /* Fault from a previous inst? */ + FPFault = 0; + t = (GetMap(040) + 1) & AMASK; /* Yes: 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-1) & AMASK)); + if (C) PutMap(t, (GetMap(t) | 0100000)); + PutMap(040, t); + PC = indirect(GetMap(045)); /* JMP indirect to 45 */ + continue; + } + FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */ + FPSR |= ((PC - 1) & AMASK); + if (FPSR & 0x02000000) /* Z is on? */ + PC = (PC + 1) & AMASK; /* yep: skip */ continue; } - if (IR == 0133250) { /* FSLE */ - if (!(fpu_unit.flags & UNIT_UP)) - continue; + if (IR == 0133250) { /* FSLE */ + if (!(fpu_unit.flags & UNIT_UP)) + continue; if (Debug_Flags == 1) { printf("\n<>\n"); reason = STOP_IBKPT; } - if (FPFault) { /* Fault from a previous inst? */ - FPFault = 0; - t = (GetMap(040) + 1) & AMASK; /* Yes: 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-1) & AMASK)); - if (C) PutMap(t, (GetMap(t) | 0100000)); - PutMap(040, t); - PC = indirect(GetMap(045)); /* JMP indirect to 45 */ - continue; - } - FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */ - FPSR |= ((PC - 1) & AMASK); - if (FPSR & 0x03000000) /* Z or N on? */ - PC = (PC + 1) & AMASK; /* yep: skip */ + if (FPFault) { /* Fault from a previous inst? */ + FPFault = 0; + t = (GetMap(040) + 1) & AMASK; /* Yes: 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-1) & AMASK)); + if (C) PutMap(t, (GetMap(t) | 0100000)); + PutMap(040, t); + PC = indirect(GetMap(045)); /* JMP indirect to 45 */ + continue; + } + FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */ + FPSR |= ((PC - 1) & AMASK); + if (FPSR & 0x03000000) /* Z or N on? */ + PC = (PC + 1) & AMASK; /* yep: skip */ continue; } - if (IR == 0127250) { /* FSGE */ - if (!(fpu_unit.flags & UNIT_UP)) - continue; + if (IR == 0127250) { /* FSGE */ + if (!(fpu_unit.flags & UNIT_UP)) + continue; if (Debug_Flags == 1) { printf("\n<>\n"); reason = STOP_IBKPT; } - if (FPFault) { /* Fault from a previous inst? */ - FPFault = 0; - t = (GetMap(040) + 1) & AMASK; /* Yes: 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-1) & AMASK)); - if (C) PutMap(t, (GetMap(t) | 0100000)); - PutMap(040, t); - PC = indirect(GetMap(045)); /* JMP indirect to 45 */ - continue; - } - FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */ - FPSR |= ((PC - 1) & AMASK); - if (!(FPSR & 0x01000000)) /* N is off? */ - PC = (PC + 1) & AMASK; /* yep: skip */ + if (FPFault) { /* Fault from a previous inst? */ + FPFault = 0; + t = (GetMap(040) + 1) & AMASK; /* Yes: 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-1) & AMASK)); + if (C) PutMap(t, (GetMap(t) | 0100000)); + PutMap(040, t); + PC = indirect(GetMap(045)); /* JMP indirect to 45 */ + continue; + } + FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */ + FPSR |= ((PC - 1) & AMASK); + if (!(FPSR & 0x01000000)) /* N is off? */ + PC = (PC + 1) & AMASK; /* yep: skip */ continue; } - if (IR == 0117250) { /* FSNE */ - if (!(fpu_unit.flags & UNIT_UP)) - continue; + if (IR == 0117250) { /* FSNE */ + if (!(fpu_unit.flags & UNIT_UP)) + continue; if (Debug_Flags == 1) { printf("\n<>\n"); - continue; + continue; } - if (FPFault) { /* Fault from a previous inst? */ - FPFault = 0; - t = (GetMap(040) + 1) & AMASK; /* Yes: 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-1) & AMASK)); - if (C) PutMap(t, (GetMap(t) | 0100000)); - PutMap(040, t); - PC = indirect(GetMap(045)); /* JMP indirect to 45 */ - continue; - } - FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */ - FPSR |= ((PC - 1) & AMASK); - if (!(FPSR & 0x02000000)) /* Z is off? */ - PC = (PC + 1) & AMASK; /* yep: skip */ + if (FPFault) { /* Fault from a previous inst? */ + FPFault = 0; + t = (GetMap(040) + 1) & AMASK; /* Yes: 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-1) & AMASK)); + if (C) PutMap(t, (GetMap(t) | 0100000)); + PutMap(040, t); + PC = indirect(GetMap(045)); /* JMP indirect to 45 */ + continue; + } + FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */ + FPSR |= ((PC - 1) & AMASK); + if (!(FPSR & 0x02000000)) /* Z is off? */ + PC = (PC + 1) & AMASK; /* yep: skip */ continue; } - if (IR == 0143250) { /* FSNM */ - if (!(fpu_unit.flags & UNIT_UP)) - continue; + if (IR == 0143250) { /* FSNM */ + if (!(fpu_unit.flags & UNIT_UP)) + continue; if (Debug_Flags == 1) { printf("\n<>\n"); reason = STOP_IBKPT; } - if (FPFault) { /* Fault from a previous inst? */ - FPFault = 0; - t = (GetMap(040) + 1) & AMASK; /* Yes: 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-1) & AMASK)); - if (C) PutMap(t, (GetMap(t) | 0100000)); - PutMap(040, t); - PC = indirect(GetMap(045)); /* JMP indirect to 45 */ - continue; - } - FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */ - FPSR |= ((PC - 1) & AMASK); - if (!(FPSR & 0x08000000)) /* MOF is off? */ - PC = (PC + 1) & AMASK; /* yep: skip */ + if (FPFault) { /* Fault from a previous inst? */ + FPFault = 0; + t = (GetMap(040) + 1) & AMASK; /* Yes: 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-1) & AMASK)); + if (C) PutMap(t, (GetMap(t) | 0100000)); + PutMap(040, t); + PC = indirect(GetMap(045)); /* JMP indirect to 45 */ + continue; + } + FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */ + FPSR |= ((PC - 1) & AMASK); + if (!(FPSR & 0x08000000)) /* MOF is off? */ + PC = (PC + 1) & AMASK; /* yep: skip */ continue; } - if (IR == 0153250) { /* FSNU */ - if (!(fpu_unit.flags & UNIT_UP)) - continue; + if (IR == 0153250) { /* FSNU */ + if (!(fpu_unit.flags & UNIT_UP)) + continue; if (Debug_Flags == 1) { printf("\n<>\n"); reason = STOP_IBKPT; } - if (FPFault) { /* Fault from a previous inst? */ - FPFault = 0; - t = (GetMap(040) + 1) & AMASK; /* Yes: 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-1) & AMASK)); - if (C) PutMap(t, (GetMap(t) | 0100000)); - PutMap(040, t); - PC = indirect(GetMap(045)); /* JMP indirect to 45 */ - continue; - } - FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */ - FPSR |= ((PC - 1) & AMASK); - if (!(FPSR & 0x20000000)) /* UNF is off? */ - PC = (PC + 1) & AMASK; /* yep: skip */ + if (FPFault) { /* Fault from a previous inst? */ + FPFault = 0; + t = (GetMap(040) + 1) & AMASK; /* Yes: 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-1) & AMASK)); + if (C) PutMap(t, (GetMap(t) | 0100000)); + PutMap(040, t); + PC = indirect(GetMap(045)); /* JMP indirect to 45 */ + continue; + } + FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */ + FPSR |= ((PC - 1) & AMASK); + if (!(FPSR & 0x20000000)) /* UNF is off? */ + PC = (PC + 1) & AMASK; /* yep: skip */ continue; } - if (IR == 0163250) { /* FSNO */ - if (!(fpu_unit.flags & UNIT_UP)) - continue; + if (IR == 0163250) { /* FSNO */ + if (!(fpu_unit.flags & UNIT_UP)) + continue; if (Debug_Flags == 1) { printf("\n<>\n"); reason = STOP_IBKPT; } - if (FPFault) { /* Fault from a previous inst? */ - FPFault = 0; - t = (GetMap(040) + 1) & AMASK; /* Yes: 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-1) & AMASK)); - if (C) PutMap(t, (GetMap(t) | 0100000)); - PutMap(040, t); - PC = indirect(GetMap(045)); /* JMP indirect to 45 */ - continue; - } - FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */ - FPSR |= ((PC - 1) & AMASK); - if (!(FPSR & 0x40000000)) /* OVF is off? */ - PC = (PC + 1) & AMASK; /* yep: skip */ + if (FPFault) { /* Fault from a previous inst? */ + FPFault = 0; + t = (GetMap(040) + 1) & AMASK; /* Yes: 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-1) & AMASK)); + if (C) PutMap(t, (GetMap(t) | 0100000)); + PutMap(040, t); + PC = indirect(GetMap(045)); /* JMP indirect to 45 */ + continue; + } + FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */ + FPSR |= ((PC - 1) & AMASK); + if (!(FPSR & 0x40000000)) /* OVF is off? */ + PC = (PC + 1) & AMASK; /* yep: skip */ continue; } - if (IR == 0147250) { /* FSND */ - if (!(fpu_unit.flags & UNIT_UP)) - continue; + if (IR == 0147250) { /* FSND */ + if (!(fpu_unit.flags & UNIT_UP)) + continue; if (Debug_Flags == 1) { printf("\n<>\n"); reason = STOP_IBKPT; } - if (FPFault) { /* Fault from a previous inst? */ - FPFault = 0; - t = (GetMap(040) + 1) & AMASK; /* Yes: 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-1) & AMASK)); - if (C) PutMap(t, (GetMap(t) | 0100000)); - PutMap(040, t); - PC = indirect(GetMap(045)); /* JMP indirect to 45 */ - continue; - } - FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */ - FPSR |= ((PC - 1) & AMASK); - if (!(FPSR & 0x10000000)) /* DVZ is off? */ - PC = (PC + 1) & AMASK; /* yep: skip */ + if (FPFault) { /* Fault from a previous inst? */ + FPFault = 0; + t = (GetMap(040) + 1) & AMASK; /* Yes: 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-1) & AMASK)); + if (C) PutMap(t, (GetMap(t) | 0100000)); + PutMap(040, t); + PC = indirect(GetMap(045)); /* JMP indirect to 45 */ + continue; + } + FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */ + FPSR |= ((PC - 1) & AMASK); + if (!(FPSR & 0x10000000)) /* DVZ is off? */ + PC = (PC + 1) & AMASK; /* yep: skip */ continue; } - if (IR == 0157250) { /* FSNUD */ - if (!(fpu_unit.flags & UNIT_UP)) - continue; + if (IR == 0157250) { /* FSNUD */ + if (!(fpu_unit.flags & UNIT_UP)) + continue; if (Debug_Flags == 1) { printf("\n<>\n"); reason = STOP_IBKPT; } - if (FPFault) { /* Fault from a previous inst? */ - FPFault = 0; - t = (GetMap(040) + 1) & AMASK; /* Yes: 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-1) & AMASK)); - if (C) PutMap(t, (GetMap(t) | 0100000)); - PutMap(040, t); - PC = indirect(GetMap(045)); /* JMP indirect to 45 */ - continue; - } - FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */ - FPSR |= ((PC - 1) & AMASK); - if (!(FPSR & 0x30000000)) /* UNF & DVZ off? */ - PC = (PC + 1) & AMASK; /* yep: skip */ + if (FPFault) { /* Fault from a previous inst? */ + FPFault = 0; + t = (GetMap(040) + 1) & AMASK; /* Yes: 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-1) & AMASK)); + if (C) PutMap(t, (GetMap(t) | 0100000)); + PutMap(040, t); + PC = indirect(GetMap(045)); /* JMP indirect to 45 */ + continue; + } + FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */ + FPSR |= ((PC - 1) & AMASK); + if (!(FPSR & 0x30000000)) /* UNF & DVZ off? */ + PC = (PC + 1) & AMASK; /* yep: skip */ continue; } - if (IR == 0167250) { /* FSNOD */ - if (!(fpu_unit.flags & UNIT_UP)) - continue; + if (IR == 0167250) { /* FSNOD */ + if (!(fpu_unit.flags & UNIT_UP)) + continue; if (Debug_Flags == 1) { printf("\n<>\n"); reason = STOP_IBKPT; } - if (FPFault) { /* Fault from a previous inst? */ - FPFault = 0; - t = (GetMap(040) + 1) & AMASK; /* Yes: 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-1) & AMASK)); - if (C) PutMap(t, (GetMap(t) | 0100000)); - PutMap(040, t); - PC = indirect(GetMap(045)); /* JMP indirect to 45 */ - continue; - } - FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */ - FPSR |= ((PC - 1) & AMASK); - if (!(FPSR & 0x50000000)) /* OVF & DVZ off? */ - PC = (PC + 1) & AMASK; /* yep: skip */ + if (FPFault) { /* Fault from a previous inst? */ + FPFault = 0; + t = (GetMap(040) + 1) & AMASK; /* Yes: 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-1) & AMASK)); + if (C) PutMap(t, (GetMap(t) | 0100000)); + PutMap(040, t); + PC = indirect(GetMap(045)); /* JMP indirect to 45 */ + continue; + } + FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */ + FPSR |= ((PC - 1) & AMASK); + if (!(FPSR & 0x50000000)) /* OVF & DVZ off? */ + PC = (PC + 1) & AMASK; /* yep: skip */ continue; } - if (IR == 0173250) { /* FSNUO */ - if (!(fpu_unit.flags & UNIT_UP)) - continue; + if (IR == 0173250) { /* FSNUO */ + if (!(fpu_unit.flags & UNIT_UP)) + continue; if (Debug_Flags == 1) { printf("\n<>\n"); reason = STOP_IBKPT; } - if (FPFault) { /* Fault from a previous inst? */ - FPFault = 0; - t = (GetMap(040) + 1) & AMASK; /* Yes: 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-1) & AMASK)); - if (C) PutMap(t, (GetMap(t) | 0100000)); - PutMap(040, t); - PC = indirect(GetMap(045)); /* JMP indirect to 45 */ - continue; - } - FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */ - FPSR |= ((PC - 1) & AMASK); - if (!(FPSR & 0x60000000)) /* OVF & UNF off? */ - PC = (PC + 1) & AMASK; /* yep: skip */ + if (FPFault) { /* Fault from a previous inst? */ + FPFault = 0; + t = (GetMap(040) + 1) & AMASK; /* Yes: 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-1) & AMASK)); + if (C) PutMap(t, (GetMap(t) | 0100000)); + PutMap(040, t); + PC = indirect(GetMap(045)); /* JMP indirect to 45 */ + continue; + } + FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */ + FPSR |= ((PC - 1) & AMASK); + if (!(FPSR & 0x60000000)) /* OVF & UNF off? */ + PC = (PC + 1) & AMASK; /* yep: skip */ continue; } - if (IR == 0177250) { /* FSNER */ - if (!(fpu_unit.flags & UNIT_UP)) - continue; + if (IR == 0177250) { /* FSNER */ + if (!(fpu_unit.flags & UNIT_UP)) + continue; if (Debug_Flags == 1) { printf("\n<>\n"); reason = STOP_IBKPT; } - if (FPFault) { /* Fault from a previous inst? */ - FPFault = 0; - t = (GetMap(040) + 1) & AMASK; /* Yes: 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-1) & AMASK)); - if (C) PutMap(t, (GetMap(t) | 0100000)); - PutMap(040, t); - PC = indirect(GetMap(045)); /* JMP indirect to 45 */ - continue; - } - FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */ - FPSR |= ((PC - 1) & AMASK); - if (!(FPSR & 0x78000000)) /* all errors off? */ - PC = (PC + 1) & AMASK; /* yep: skip */ + if (FPFault) { /* Fault from a previous inst? */ + FPFault = 0; + t = (GetMap(040) + 1) & AMASK; /* Yes: 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-1) & AMASK)); + if (C) PutMap(t, (GetMap(t) | 0100000)); + PutMap(040, t); + PC = indirect(GetMap(045)); /* JMP indirect to 45 */ + continue; + } + FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */ + FPSR |= ((PC - 1) & AMASK); + if (!(FPSR & 0x78000000)) /* all errors off? */ + PC = (PC + 1) & AMASK; /* yep: skip */ continue; } @@ -4684,45 +4694,45 @@ if ((IR & 0100017) == 0100010) { /* This pattern for all */ } } -if (IR == 061777) { /* VCT: Vector on Interrupt */ +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 */ + 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); + 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; - } + if (iodata & dev_table[i].mask) { + iodev = i; + break; + } } - ventry = GetMap(vtable + iodev); /* Get Vector Entry */ + ventry = GetMap(vtable + iodev); /* Get Vector Entry */ - if (!(ventry & 0100000)) { /* Direct bit = 0? */ - PC = ventry & AMASK; /* YES - Mode A, so JMP */ + if (!(ventry & 0100000)) { /* Direct bit = 0? */ + PC = ventry & AMASK; /* YES - Mode A, so JMP */ continue; } - dctadr = ventry & AMASK; /* Get address of DCT entry */ + dctadr = ventry & AMASK; /* Get address of DCT entry */ - if (stkchg) { /* Stack change bit = 1? */ - old40 = GetMap(040); /* Save stack info */ + 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(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); @@ -4732,572 +4742,585 @@ if (IR == 061777) { /* VCT: Vector on Interrupt */ PutMap(GetMap(040) & AMASK, old43); } - t = GetMap(dctadr & AMASK); /* Get word 0 of DCT */ + t = GetMap(dctadr & AMASK); /* Get word 0 of DCT */ - if (t & 0100000) { /* Push bit set ? */ - PutMap(040, (GetMap(040) + 1)); /* Push "Standard rtn block" */ + 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(040, (GetMap(040) + 1)); PutMap(GetMap(040) & AMASK, AC[1]); - PutMap(040, (GetMap(040) + 1)); + PutMap(040, (GetMap(040) + 1)); PutMap(GetMap(040) & AMASK, AC[2]); - PutMap(040, (GetMap(040) + 1)); + PutMap(040, (GetMap(040) + 1)); PutMap(GetMap(040) & AMASK, AC[3]); - PutMap(040, (GetMap(040) + 1)); + 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)); + 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 */ - AC[2] = dctadr & AMASK; /* DCT Addr into AC2 */ - - PutMap(040, (GetMap(040) + 1)); /* Push pri int mask onto stack */ + 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 */ + 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 */ + mask_out(pimask = AC[0]); /* Do a mask out inst */ - PC = GetMap(dctadr) & AMASK; /* Finally, JMP to int routine */ + PC = GetMap(dctadr) & AMASK; /* Finally, JMP to int routine */ continue; } +/************************************************************************* +** At this point, the instruction is not an Eclipse one. Therefore ** +** decode it as a Nova instruction just like the Nova does. ** +*************************************************************************/ + /* 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-1)) { - 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 */ +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-1)) { + if ((MapStat & 010) && Usermap) { + Fault = 04000; /* Map fault if IND prot */ + continue; + } + if (i >= (ind_max * 2) && !(Fault)) { + reason = STOP_IND; + break; + } + } + } + + 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 */ - 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 */ +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 */ + + 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 */ - 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) /* LEF mode bit on? */ - && 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; - continue; +else { /* IOT */ + register int32 dstAC, pulse, code, device, iodata; + char pulcode[4]; + + if ((MapStat & 0100) /* LEF mode bit on? */ + && 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; } - if ((Debug_Flags & 0100) && (device == (Debug_Flags & 077))) { - printf("\n\r<>\n\r", device); - reason = STOP_IBKPT; - continue; - } - if ((Debug_Char != 0) && (device == 011) && - ((AC[dstAC] & 0177) == Debug_Char)) { - printf("\n\r<>\n\r", Debug_Char); - reason = STOP_IBKPT; - continue; - } - 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 */ + 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; + continue; + } + if ((Debug_Flags & 0100) && (device == (Debug_Flags & 077))) { + printf("\n\r<>\n\r", device); + reason = STOP_IBKPT; + continue; + } + if ((Debug_Char != 0) && (device == 011) && + ((AC[dstAC] & 0177) == Debug_Char)) { + printf("\n\r<>\n\r", Debug_Char); + reason = STOP_IBKPT; + continue; + } + 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 */ - 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; - FPSR &= 0x0000FFFF; - FPFault = 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_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; + FPSR &= 0x0000FFFF; + FPFault = 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 */ +//AOS 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; +//AOS } else { +//AOS if ((Debug_Flags & 077) == 03) +//AOS fprintf(Trace, "%o DOB %o=%o (Map Blk 31) NO EXEC (User Mode)\n", PC-1, dstAC, AC[dstAC]); +//AOS } + 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 */ - 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 */ -//AOS 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; -//AOS } else { -//AOS if ((Debug_Flags & 077) == 03) -//AOS fprintf(Trace, "%o DOB %o=%o (Map Blk 31) NO EXEC (User Mode)\n", PC-1, dstAC, AC[dstAC]); -//AOS } - 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; @@ -5310,41 +5333,42 @@ return reason; 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 */ + register int32 i, MA; - 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-1) && (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); + 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-1) && (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 @@ -5355,52 +5379,53 @@ int32 effective(int32 PC, int32 index, int32 disp) 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 */ - sMA = MA; - if (MA & 0200) sMA |= 0xff00; - MA = (sMA + 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 */ + register int32 i, MA; + int16 sMA; - 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-1) && (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); + MA = disp & 077777; + switch (index) { /* decode IR<6:7> */ + case 0: /* page zero */ + break; + case 1: /* PC relative */ + sMA = MA; + if (MA & 0200) sMA |= 0xff00; + MA = (sMA + 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-1) && (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 */ @@ -5408,24 +5433,25 @@ int32 LEFmode(int32 PC, int32 index, int32 disp, int32 indirect) 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 + GetMap(PC); - return (MA & 0177777); + 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 + GetMap(PC); + return (MA & 0177777); } /* Given an address, returns either that address if bit 0 is 0, or @@ -5434,51 +5460,51 @@ int32 Bytepointer(int32 PC, int32 index) 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-1) && (MapStat & 010) && Usermap) { - Fault = 04000; /* Map fault if IND prot */ - } - if (i >= (ind_max * 2) && !(Fault)) { - reason = STOP_IND; /* Stop machine */ - } - } - return (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-1) && (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; + 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 */ @@ -5486,7 +5512,7 @@ int32 pushrtn(int32 pc) int32 GetMap(int32 addr) { int32 page; - t_addr paddr; + t_addr paddr; switch (Usermap) { case 0: @@ -5502,7 +5528,7 @@ int32 GetMap(int32 addr) page = (addr >> 10) & 037; paddr = ((Map[1][page] & 01777) << 10) | (addr & 001777); if (Map[1][page] == INVALID && !SingleCycle) - Fault = 0100000/*!!!*/; /* Validity */ + Fault = 0100000/*!!!*/; /* Validity */ if (paddr < MEMSIZE) return M[paddr]; else @@ -5512,7 +5538,7 @@ int32 GetMap(int32 addr) page = (addr >> 10) & 037; paddr = ((Map[2][page] & PAGEMASK) << 10) | (addr & 001777); if (Map[2][page] == INVALID && !SingleCycle) - Fault = 0100000/*!!!*/; /* Validity */ + Fault = 0100000/*!!!*/; /* Validity */ if (paddr < MEMSIZE) return M[paddr]; else @@ -5522,7 +5548,7 @@ int32 GetMap(int32 addr) page = (addr >> 10) & 037; paddr = ((Map[6][page] & PAGEMASK) << 10) | (addr & 001777); if (Map[6][page] == INVALID && !SingleCycle) - Fault = 0100000/*!!!*/; /* Validity */ + Fault = 0100000/*!!!*/; /* Validity */ if (paddr < MEMSIZE) return M[paddr]; else @@ -5532,7 +5558,7 @@ int32 GetMap(int32 addr) page = (addr >> 10) & 037; paddr = ((Map[7][page] & PAGEMASK) << 10) | (addr & 001777); if (Map[7][page] == INVALID && !SingleCycle) - Fault = 0100000/*!!!*/; /* Validity */ + Fault = 0100000/*!!!*/; /* Validity */ if (paddr < MEMSIZE) return M[paddr]; else @@ -5548,7 +5574,7 @@ int32 GetMap(int32 addr) int32 PutMap(int32 addr, int32 data) { int32 page; - t_addr paddr; + t_addr paddr; switch (Usermap) { case 0: @@ -5563,28 +5589,28 @@ int32 PutMap(int32 addr, int32 data) 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; /* Write Protect Fault */ + Fault = 010000; /* Write Protect Fault */ 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; /* Write Protect Fault */ + Fault = 010000; /* Write Protect Fault */ 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; /* Write Protect Fault */ + Fault = 010000; /* Write Protect Fault */ 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; /* Write Protect Fault */ + Fault = 010000; /* Write Protect Fault */ else if (paddr < MEMSIZE) M[paddr] = data; break; default: @@ -5614,7 +5640,7 @@ int16 PutDCHMap(int32 map, int32 addr, int16 data) } paddr = ((Map[map][(addr >> 10) & 037] & PAGEMASK) << 10) | (addr & 001777); if (paddr < MEMSIZE) - M[paddr] = data; + M[paddr] = data; return (data); } #endif @@ -5641,34 +5667,34 @@ int32 LoadMap(int32 w) m = (w >> 10) & 037; switch ((MapStat >> 7) & 07) { - case 0: /* Load user A Map */ + case 0: /* Load user A Map */ Map[1][m] = w & MAPMASK; break; - case 1: /* Load user C Map */ + case 1: /* Load user C Map */ Map[6][m] = w & MAPMASK; - break; - case 2: /* Load user B Map */ + 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 */ + 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 */ + break; + case 5: /* Load DCH C Map */ Map[4][m] = w; - break; - case 6: /* Load DCH B Map */ + break; + case 6: /* Load DCH B Map */ Map[3][m] = w; - break; - case 7: /* Load DCH D Map */ + break; + case 7: /* Load DCH D Map */ Map[5][m] = w; - break; + break; default: break; } - return 0; + return 0; } /* Displays an error on a unimplemented (in this sim) instr. */ @@ -5677,7 +5703,7 @@ int32 unimp(int32 PC) { if (Debug_Flags) printf("\n\r\007<<>>\n\r", PC - 1, GetMap(PC - 1)); - return 0; + return 0; } /* New priority mask out */ @@ -5688,12 +5714,13 @@ 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; } + 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) @@ -5711,10 +5738,13 @@ return SCPE_OK; t_stat cpu_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw) { if (sw & SWMASK ('V')) { - if (addr > 077777) return SCPE_NXM; - if (vptr != NULL) *vptr = GetMap (addr); } -else { if (addr >= MEMSIZE) return SCPE_NXM; - if (vptr != NULL) *vptr = M[addr] & 0177777; } + if (addr > 077777) return SCPE_NXM; + if (vptr != NULL) *vptr = GetMap (addr); +} +else { + if (addr >= MEMSIZE) return SCPE_NXM; + if (vptr != NULL) *vptr = M[addr] & 0177777; +} return SCPE_OK; } @@ -5723,10 +5753,13 @@ return SCPE_OK; t_stat cpu_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw) { if (sw & SWMASK ('V')) { - if (addr > 077777) return SCPE_NXM; - PutMap (addr, (int32) val); } -else { if (addr >= MEMSIZE) return SCPE_NXM; - M[addr] = (int32) val & 0177777; } + if (addr > 077777) return SCPE_NXM; + PutMap (addr, (int32) val); +} +else { + if (addr >= MEMSIZE) return SCPE_NXM; + M[addr] = (int32) val & 0177777; +} return SCPE_OK; } @@ -5738,10 +5771,10 @@ int32 mc = 0; t_addr i; if ((val <= 0) || (val > MAXMEMSIZE) || ((val & 07777) != 0)) - return SCPE_ARG; + 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; + return SCPE_OK; MEMSIZE = val; for (i = MEMSIZE; i < MAXMEMSIZE; i++) M[i] = 0; return SCPE_OK; @@ -5759,7 +5792,7 @@ return SCPE_OK; 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 */ +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; } @@ -5769,7 +5802,7 @@ return SCPE_OK; 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 */ +uptr->u4 = -2; /* signal to print_sys in eclipse_sys.c: do not map */ Map[(addr >> 6) & 3][addr & 037] = (int32)val & 0177777; return SCPE_OK; } @@ -5789,33 +5822,33 @@ int32 pit (int32 pulse, int32 code, int32 AC) { int32 iodata = 0; -if (code == ioDIA) { /* DIA */ - if (pit_flag == 0) { - pit_flag = 1; - } - iodata = pit_counter; +if (code == ioDIA) { /* DIA */ + if (pit_flag == 0) { + pit_flag = 1; + } + iodata = pit_counter; } -if (code == ioDOA) { /* DOA */ - pit_initial = AC; /* Load Counter */ - sim_rtcn_init (pit_time, 1); /* init calibr */ +if (code == ioDOA) { /* DOA */ + pit_initial = AC; /* Load Counter */ + sim_rtcn_init (pit_time, 1); /* init calibr */ } -switch (pulse) { /* decode IR<8:9> */ -case iopS: /* start */ - pit_counter = pit_initial; /* Set the counter */ - dev_busy = dev_busy | INT_PIT; /* set busy */ - dev_done = dev_done & ~INT_PIT; /* clear done, int */ - int_req = int_req & ~INT_PIT; - if (!sim_is_active (&pit_unit)) /* not running? */ - sim_activate (&pit_unit, /* activate */ - sim_rtcn_init (pit_time, 1)); /* init calibr */ - break; -case iopC: /* clear */ - dev_busy = dev_busy & ~INT_PIT; /* clear busy */ - dev_done = dev_done & ~INT_PIT; /* clear done, int */ - int_req = int_req & ~INT_PIT; - sim_cancel (&pit_unit); /* deactivate unit */ - break; } /* end switch */ -return iodata; +switch (pulse) { /* decode IR<8:9> */ +case iopS: /* start */ + pit_counter = pit_initial; /* Set the counter */ + dev_busy = dev_busy | INT_PIT; /* set busy */ + dev_done = dev_done & ~INT_PIT; /* clear done, int */ + int_req = int_req & ~INT_PIT; + if (!sim_is_active (&pit_unit)) /* not running? */ + sim_activate (&pit_unit, /* activate */ + sim_rtcn_init (pit_time, 1)); /* init calibr */ + break; +case iopC: /* clear */ + dev_busy = dev_busy & ~INT_PIT; /* clear busy */ + dev_done = dev_done & ~INT_PIT; /* clear done, int */ + int_req = int_req & ~INT_PIT; + sim_cancel (&pit_unit); /* deactivate unit */ + break; } /* end switch */ +return iodata; } /* Unit service */ @@ -5823,15 +5856,15 @@ return iodata; t_stat pit_svc (UNIT *uptr) { int32 t; -t = sim_rtcn_calb (pit_tps, 1); /* calibrate delay */ -sim_activate (&pit_unit, t); /* reactivate unit */ -pit_poll = t / (-pit_adj); /* adjust poll */ -pit_counter++; /* Increment counter */ -if (pit_counter >= 0177777) { /* Has counter reached limit ? */ - dev_done = dev_done | INT_PIT; /* set done */ - dev_busy = dev_busy & ~INT_PIT; /* clear busy */ - int_req = (int_req & ~INT_DEV) | (dev_done & ~dev_disable); /* Interrupt */ - pit_counter = pit_initial; +t = sim_rtcn_calb (pit_tps, 1); /* calibrate delay */ +sim_activate (&pit_unit, t); /* reactivate unit */ +pit_poll = t / (-pit_adj); /* adjust poll */ +pit_counter++; /* Increment counter */ +if (pit_counter >= 0177777) { /* Has counter reached limit ? */ + dev_done = dev_done | INT_PIT; /* set done */ + dev_busy = dev_busy & ~INT_PIT; /* clear busy */ + int_req = (int_req & ~INT_DEV) | (dev_done & ~dev_disable); /* Interrupt */ + pit_counter = pit_initial; } return SCPE_OK; } @@ -5840,12 +5873,12 @@ return SCPE_OK; t_stat pit_reset (DEVICE *dptr) { -pit_counter = 0; /* clear counter */ -dev_busy = dev_busy & ~INT_PIT; /* clear busy */ -dev_done = dev_done & ~INT_PIT; /* clear done, int */ +pit_counter = 0; /* clear counter */ +dev_busy = dev_busy & ~INT_PIT; /* clear busy */ +dev_done = dev_done & ~INT_PIT; /* clear done, int */ int_req = int_req & ~INT_PIT; -sim_cancel (&pit_unit); /* deactivate unit */ -pit_poll = pit_time; /* poll is default */ +sim_cancel (&pit_unit); /* deactivate unit */ +pit_poll = pit_time; /* poll is default */ return SCPE_OK; } @@ -5855,41 +5888,42 @@ return SCPE_OK; #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 */ + + 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) @@ -5917,12 +5951,12 @@ int32 Debug_Entry(int32 PC, int32 inst, int32 inst2, int32 AC0, int32 AC1, int32 hwrap = 1; hnext = 0; } - return 0; + return 0; } int32 Debug_Dump(UNIT *uptr, int32 val, char *cptr, void *desc) { - return SCPE_OK; + return SCPE_OK; } int32 Dump_History (FILE *st, UNIT *uptr, int32 val, void *desc) @@ -5939,14 +5973,14 @@ int32 Dump_History (FILE *st, UNIT *uptr, int32 val, void *desc) return SCPE_OK; } if (!hwrap) { - start = 0; - end = hnext; + start = 0; + end = hnext; } else { start = hnext; - end = hnext - 1; - if (end < 0) end = hmax; + end = hnext - 1; + if (end < 0) end = hmax; } - ctr = start; + ctr = start; while (1) { if (ctr == end) break; @@ -5956,7 +5990,7 @@ int32 Dump_History (FILE *st, UNIT *uptr, int32 val, void *desc) debcar = 0; if (hflags[ctr] & 0x80) { fprintf(st, "--------- Interrupt %o (%o) to %6o ---------\n", - hinst[ctr], hac0[ctr], hac1[ctr]); + hinst[ctr], hac0[ctr], hac1[ctr]); } else { if (hflags[ctr] & 0x01) debcar = 1; if (hflags[ctr] & 0x02) strcpy(debion, "I"); @@ -5965,8 +5999,8 @@ int32 Dump_History (FILE *st, UNIT *uptr, int32 val, void *desc) if (hflags[ctr] & 0x10) strcpy(debmap, "C"); if (hflags[ctr] & 0x20) strcpy(debmap, "D"); fprintf(st, "%s%s%06o acs: %06o %06o %06o %06o %01o ", - debion, debmap, hpc[ctr], hac0[ctr], hac1[ctr], hac2[ctr], - hac3[ctr], debcar); + debion, debmap, hpc[ctr], hac0[ctr], hac1[ctr], hac2[ctr], + hac3[ctr], debcar); simeval[0] = hinst[ctr]; simeval[1] = hinst2[ctr]; fprint_sym (st, hpc[ctr], simeval, NULL, SWMASK('M')); @@ -5976,7 +6010,7 @@ int32 Dump_History (FILE *st, UNIT *uptr, int32 val, void *desc) if (ctr > hmax) ctr = 0; } - return SCPE_OK; + return SCPE_OK; } /* Build dispatch table */ @@ -5987,17 +6021,20 @@ 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 (!(dptr->flags & DEV_DIS) && /* enabled and */ - (dibp = (DIB *) dptr->ctxt)) { /* defined 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; } } +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 (!(dptr->flags & DEV_DIS) && /* enabled and */ + (dibp = (DIB *) dptr->ctxt)) { /* defined 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; } @@ -6080,7 +6117,7 @@ int normal_sf(SHORT_FLOAT *fl) fl->expo = 0; } if (fl->expo < 0) - return (2); + return (2); return(0); } @@ -6110,7 +6147,7 @@ int normal_lf (LONG_FLOAT *fl) fl->expo = 0; } if (fl->expo < 0) - return (2); + return (2); return(0); } @@ -6129,9 +6166,9 @@ int overflow_lf(LONG_FLOAT *fl) int underflow_sf(SHORT_FLOAT *fl) { if (fl->expo < 0) { - fl->short_fract = 0; - fl->expo = 0; - fl->sign = 0; + fl->short_fract = 0; + fl->expo = 0; + fl->sign = 0; } return(0); @@ -6141,9 +6178,9 @@ int underflow_sf(SHORT_FLOAT *fl) int underflow_lf(LONG_FLOAT *fl) { if (fl->expo < 0) { - fl->long_fract = 0; - fl->expo = 0; - fl->sign = 0; + fl->long_fract = 0; + fl->expo = 0; + fl->sign = 0; } return(0); } @@ -6157,10 +6194,10 @@ int over_under_flow_sf(SHORT_FLOAT *fl) return(1); } else { if (fl->expo < 0) { - /* set true 0 */ - fl->short_fract = 0; - fl->expo = 0; - fl->sign = 0; + /* set true 0 */ + fl->short_fract = 0; + fl->expo = 0; + fl->sign = 0; } } return(0); @@ -6176,10 +6213,10 @@ int over_under_flow_lf(LONG_FLOAT *fl) return(1); } else { if (fl->expo < 0) { - /* set true 0 */ - fl->long_fract = 0; - fl->expo = 0; - fl->sign = 0; + /* set true 0 */ + fl->long_fract = 0; + fl->expo = 0; + fl->sign = 0; } } return(0); @@ -6220,9 +6257,9 @@ int shift; pgm_check = 0; if (add_fl->short_fract - || add_fl->expo) { /* add_fl not 0 */ + || add_fl->expo) { /* add_fl not 0 */ if (fl->short_fract - || fl->expo) { /* fl not 0 */ + || fl->expo) { /* fl not 0 */ /* both not 0 */ if (fl->expo == add_fl->expo) { @@ -6316,7 +6353,7 @@ int shift; /* not 0 */ if (fl->short_fract & 0x0F000000) { - /* not normalize, just guard digit */ + /* not normalize, just guard digit */ fl->short_fract >>= 4; } else { (fl->expo)--; @@ -6337,7 +6374,7 @@ int shift; } } return(pgm_check); - } else { /* fl 0, add_fl not 0 */ + } else { /* fl 0, add_fl not 0 */ /* copy summand */ fl->expo = add_fl->expo; @@ -6347,8 +6384,8 @@ int shift; return( significance_sf(fl) ); } } - } else { /* add_fl 0 */ - if (fl->short_fract == 0) { /* fl 0 */ + } else { /* add_fl 0 */ + if (fl->short_fract == 0) { /* fl 0 */ /* both 0 */ return( significance_sf(fl) ); @@ -6380,9 +6417,9 @@ int shift; pgm_check = 0; if (add_fl->long_fract - || add_fl->expo) { /* add_fl not 0 */ + || add_fl->expo) { /* add_fl not 0 */ if (fl->long_fract - || fl->expo) { /* fl not 0 */ + || fl->expo) { /* fl not 0 */ /* both not 0 */ if (fl->expo == add_fl->expo) { @@ -6497,7 +6534,7 @@ int shift; } } return(pgm_check); - } else { /* fl 0, add_fl not 0 */ + } else { /* fl 0, add_fl not 0 */ /* copy summand */ fl->expo = add_fl->expo; @@ -6507,8 +6544,8 @@ int shift; return( significance_lf(fl) ); } } - } else { /* add_fl 0 */ - if (fl->long_fract == 0) { /* fl 0 */ + } else { /* add_fl 0 */ + if (fl->long_fract == 0) { /* fl 0 */ /* both 0 */ return( significance_lf(fl) ); @@ -6671,7 +6708,7 @@ t_int64 wk; fl->sign = 0; } } else { - /* divisor 0 */ + /* divisor 0 */ return(3); } @@ -6738,7 +6775,7 @@ int i; fl->sign = 0; } } else { - /* divisor 0 */ + /* divisor 0 */ return(3); } diff --git a/NOVA/eclipse_tt.c b/NOVA/eclipse_tt.c index 972d80f7..ab3489dd 100644 --- a/NOVA/eclipse_tt.c +++ b/NOVA/eclipse_tt.c @@ -1,23 +1,43 @@ /* eclipse_tt.c: Eclipse console terminal simulator - Copyright (c) 1998-2003, Charles E Owen + Copyright (c) 1998-2005, 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 + 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: - 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 + 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. + + 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) +#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; @@ -31,13 +51,13 @@ 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 + 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 }; @@ -45,32 +65,35 @@ 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 } }; + { 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 } }; + { 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 }; + "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 + 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 }; @@ -78,24 +101,26 @@ 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 } }; + { 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 }; - - - + "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) @@ -103,17 +128,21 @@ 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 */ +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; } @@ -123,15 +152,15 @@ 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? */ +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 */ +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; @@ -139,22 +168,22 @@ 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' */ +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. */ +/* Translation: VT100 input to D200 keycodes. */ void translate_in() { char rev = 0; if (tti_unit.buf == '\r') - rev = '\n'; + rev = '\n'; if (tti_unit.buf == '\n') - rev = '\r'; + rev = '\r'; if (rev) - tti_unit.buf = rev; + tti_unit.buf = rev; } /* -------------------- END INSERTION -----------------------*/ @@ -164,31 +193,35 @@ void translate_in() 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 */ +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 */ +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 */ +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; } @@ -198,18 +231,18 @@ 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 */ +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 --- */ + 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; } @@ -219,158 +252,158 @@ return SCPE_OK; 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 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; + 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 -----------------------*/ @@ -380,10 +413,10 @@ int32 putseq(char *seq) 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 */ +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 */ +sim_cancel (&tto_unit); /* deactivate unit */ return SCPE_OK; } diff --git a/NOVA/nova_clk.c b/NOVA/nova_clk.c index 2691a4b6..1250c935 100644 --- a/NOVA/nova_clk.c +++ b/NOVA/nova_clk.c @@ -1,6 +1,6 @@ /* nova_clk.c: NOVA real-time clock simulator - Copyright (c) 1993-2004, Robert M. Supnik + Copyright (c) 1993-2005, 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"), @@ -19,29 +19,29 @@ 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 + 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 + 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) + 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_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); @@ -51,9 +51,9 @@ 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 + 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 }; @@ -61,56 +61,64 @@ 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 } }; + { 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 } }; + { 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 }; - + "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 */ +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; } @@ -120,14 +128,14 @@ t_stat clk_svc (UNIT *uptr) { int32 t; -dev_done = dev_done | INT_CLK; /* set done */ -dev_busy = dev_busy & ~INT_CLK; /* clear busy */ +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 */ +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; } @@ -136,11 +144,11 @@ return SCPE_OK; 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 */ +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 */ +sim_cancel (&clk_unit); /* deactivate unit */ +tmxr_poll = clk_time[0]; /* poll is default */ return SCPE_OK; } diff --git a/NOVA/nova_cpu.c b/NOVA/nova_cpu.c index 417866f2..94d501c5 100644 --- a/NOVA/nova_cpu.c +++ b/NOVA/nova_cpu.c @@ -1,6 +1,6 @@ /* nova_cpu.c: NOVA CPU simulator - Copyright (c) 1993-2004, Robert M. Supnik + Copyright (c) 1993-2005, 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"), @@ -19,68 +19,69 @@ 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 + 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 + cpu Nova central processor - 14-Jan-04 RMS Fixed device enable/disable support (found by Bruce Ray) - 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 + 25-Aug-05 RMS Fixed DIVS case 2^31 / - 1 + 14-Jan-04 RMS Fixed device enable/disable support (found by Bruce Ray) + 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 + 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| op | AC |in| mode| displacement | memory reference +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - <0:4> mnemonic action + <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 + 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 + <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>)] + 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 @@ -89,13 +90,12 @@ 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: + + 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 + | 0 1 1| AC | opcode |pulse| device | I/O transfer +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ The IOT instruction sends the opcode, pulse, and specified AC to the @@ -106,66 +106,65 @@ 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 + | 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) + | | | | | | +--- 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. + 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. + 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: + 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 + 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: + 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] + 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. + 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. @@ -174,18 +173,18 @@ 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 + 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 + 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 @@ -199,61 +198,61 @@ 4. Adding I/O devices. These modules must be modified: - nova_defs.h add interrupt request definition - nova_sys.c add sim_devices entry + 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 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 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) +#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 */ +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 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); @@ -262,65 +261,69 @@ 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 + 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) }; +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 } }; + { 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 } }; + { 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 }; - + "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; @@ -331,427 +334,488 @@ 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 */ +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 */ +mask_out (pimask); /* reset int system */ reason = 0; -sim_rtc_init (clk_time[clk_sel]); /* init calibration */ +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; } +while (reason == 0) { /* loop until halted */ -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_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; } + 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; -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 */ + 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 */ + + 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; + 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 */ - 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 */ + else if (IR < 060000) { /* mem ref? */ + int32 src, MA, indf; - 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 */ + 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; + } + } + + 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 */ - 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 { /* IOT */ + int32 dstAC, pulse, code, device, iodata; - 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 */ + 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 */ + + 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) || /* overflow? */ + ((AC[0] = 0100000) && (AC[1] == 0) && (AC[2] == 0177777))) + 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 */ + + 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 */ - 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 */ +pcq_r->qptr = pcq_p; /* update pc q ptr */ return reason; } @@ -763,12 +827,13 @@ 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; } + 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) @@ -810,10 +875,10 @@ int32 mc = 0; t_addr i; if ((val <= 0) || (val > MAXMEMSIZE) || ((val & 07777) != 0)) - return SCPE_ARG; + 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; + return SCPE_OK; MEMSIZE = val; for (i = MEMSIZE; i < MAXMEMSIZE; i++) M[i] = 0; return SCPE_OK; @@ -827,62 +892,65 @@ 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 (!(dptr->flags & DEV_DIS) && /* enabled and */ - (dibp = (DIB *) dptr->ctxt)) { /* defined 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; } } +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 (!(dptr->flags & DEV_DIS) && /* enabled and */ + (dibp = (DIB *) dptr->ctxt)) { /* defined 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 */ -}; + 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) { diff --git a/NOVA/nova_defs.h b/NOVA/nova_defs.h index 9d0aa4d6..3ec5ccbd 100644 --- a/NOVA/nova_defs.h +++ b/NOVA/nova_defs.h @@ -1,6 +1,6 @@ /* nova_defs.h: NOVA/Eclipse simulator definitions - Copyright (c) 1993-2004, Robert M. Supnik + Copyright (c) 1993-2005, 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"), @@ -19,267 +19,270 @@ 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 + 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. - 14-Jan-04 BKR Added support for QTY and ALM - 22-Nov-03 CEO Added support for PIT device - 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 + 14-Jan-04 BKR Added support for QTY and ALM + 22-Nov-03 CEO Added support for PIT device + 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 */ +#ifndef _NOVA_DEFS_H_ +#define _NOVA_DEFS_H_ 0 + +#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 */ +#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 */ +#define MAXMEMSIZE 1048576 /* max memory size */ #else -#define MAXMEMSIZE 32768 /* max memory size */ +#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) +#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 */ +#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 */ +#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_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_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_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) +#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 */ +#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 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 +#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_QTY 030 /* 4060 multiplexor */ -#define DEV_DKP 033 /* disk pack */ -#define DEV_CAS 034 /* cassette */ -#define DEV_ALM 034 /* ALM/ULM multiplexor */ -#define DEV_PIT 043 /* programmable interval timer */ -#define DEV_TTI1 050 /* second console input */ -#define DEV_TTO1 051 /* second console output */ -#define DEV_CPU 077 /* CPU control */ - +#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_QTY 030 /* 4060 multiplexor */ +#define DEV_DKP 033 /* disk pack */ +#define DEV_CAS 034 /* cassette */ +#define DEV_ALM 034 /* ALM/ULM multiplexor */ +#define DEV_PIT 043 /* programmable interval timer */ +#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 + 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 */ - }; + 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; +typedef struct { + int32 dnum; /* device number */ + int32 mask; /* done/busy mask */ + int32 pi; /* assigned pi bit */ + int32 (*routine)(); /* dispatch routine */ + } DIB; /* Device flags (simulator representation) Priority (for INTA) runs from low numbers to high */ -#define INT_V_PIT 2 /* PIT */ -#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_QTY 15 /* QTY multiplexor */ -#define INT_V_ALM 16 /* ALM multiplexor */ -#define INT_V_STK 17 /* stack overflow */ -#define INT_V_NO_ION_PENDING 18 /* ion delay */ -#define INT_V_ION 19 /* interrupts on */ +#define INT_V_PIT 2 /* PIT */ +#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_QTY 15 /* QTY multiplexor */ +#define INT_V_ALM 16 /* ALM multiplexor */ +#define INT_V_STK 17 /* stack overflow */ +#define INT_V_NO_ION_PENDING 18 /* ion delay */ +#define INT_V_ION 19 /* interrupts on */ -#define INT_PIT (1 << INT_V_PIT) -#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_QTY (1 << INT_V_QTY) -#define INT_ALM (1 << INT_V_ALM) -#define INT_STK (1 << INT_V_STK) +#define INT_PIT (1 << INT_V_PIT) +#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_QTY (1 << INT_V_QTY) +#define INT_ALM (1 << INT_V_ALM) +#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 +#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_PIT 0001000 -#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_QTY 0000002 -#define PI_ALM 0000002 -#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 */ +#define PI_PIT 0001000 +#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_QTY 0000002 +#define PI_ALM 0000002 +#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); + +#endif diff --git a/NOVA/nova_dkp.c b/NOVA/nova_dkp.c index ea70e6a7..b482f630 100644 --- a/NOVA/nova_dkp.c +++ b/NOVA/nova_dkp.c @@ -1,6 +1,6 @@ /* nova_dkp.c: NOVA moving head disk simulator - Copyright (c) 1993-2004, Robert M. Supnik + Copyright (c) 1993-2005, 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"), @@ -19,47 +19,47 @@ 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 + 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 + dkp moving head disk - 04-Jan-04 RMS Changed attach routine to use sim_fsize - 28-Nov-03 CEO Boot from DP now puts device address in SR - 24-Nov-03 CEO Added support for disk sizing on 6099/6103 - 19-Nov-03 CEO Corrected major DMA Mapping bug - 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 + 04-Jan-04 RMS Changed attach routine to use sim_fsize + 28-Nov-03 CEO Boot from DP now puts device address in SR + 24-Nov-03 CEO Added support for disk sizing on 6099/6103 + 19-Nov-03 CEO Corrected major DMA Mapping bug + 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 */ +#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 @@ -67,27 +67,27 @@ 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) +#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 @@ -95,200 +95,201 @@ 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)))) ) +#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_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 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)) - + drv_tab[t].sect)+(sc)) + /* This controller supports many different disk drive types: - type #sectors/ #surfaces/ #cylinders/ new format? - surface cylinder drive + 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 + 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_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_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_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_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_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_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_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_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_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_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_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 +#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 */ -}; + 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 } }; - + { 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_map = 0; /* DCH map 0=A 3=B */ -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 */ -int32 dkp_diagmode = 0; /* diagnostic mode */ +int32 dkp_ma = 0; /* memory address */ +int32 dkp_map = 0; /* DCH map 0=A 3=B */ +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 */ +int32 dkp_diagmode = 0; /* diagnostic mode */ DEVICE dkp_dev; int32 dkp (int32 pulse, int32 code, int32 AC); @@ -301,145 +302,149 @@ 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 + 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) } }; + { 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) }, - { FLDATA (DIAG, dkp_diagmode, 0) }, - { ORDATA (MAP, dkp_map, 2) }, - { 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 } }; + { 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) }, + { FLDATA (DIAG, dkp_diagmode, 0) }, + { ORDATA (MAP, dkp_map, 2) }, + { 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 } }; + { 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 }; - + "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) @@ -448,84 +453,97 @@ 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 (AC & 0100000) /* clear rw done? */ - dkp_sta = dkp_sta & ~(STA_CYL|STA_XCY|STA_UNS|STA_CRC); - if ((dev_busy & INT_DKP) == 0) { - dkp_fccy = AC; /* save cmd, cyl */ - dkp_sta = dkp_sta & ~(AC & FCCY_FLAGS); } - if ((dkp_sta & STA_DFLGS) == 0) /* done flags = 0? */ - dev_done = dev_done & ~INT_DKP; /* clear intr */ - 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); - if (AC & 0100000) dkp_map = 3; /* high bit is map */ - else dkp_map = 0; - } - 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 */ - if (((dtype == TYPE_6099) || /* for 6099 and 6103 */ - (dtype == TYPE_6103)) && /* if data<0> set, */ - AC & 010000) dkp_diagmode = 1; /* set diagnostic mode */ - break; } /* end switch code */ - -/* IOT, continued */ +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 (AC & 0100000) /* clear rw done? */ + dkp_sta = dkp_sta & ~(STA_CYL|STA_XCY|STA_UNS|STA_CRC); + if ((dev_busy & INT_DKP) == 0) { + dkp_fccy = AC; /* save cmd, cyl */ + dkp_sta = dkp_sta & ~(AC & FCCY_FLAGS); + } + if ((dkp_sta & STA_DFLGS) == 0) /* done flags = 0? */ + dev_done = dev_done & ~INT_DKP; /* clear intr */ + 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); + if (AC & 0100000) dkp_map = 3; /* high bit is map */ + else dkp_map = 0; + } + 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 */ + if (((dtype == TYPE_6099) || /* for 6099 and 6103 */ + (dtype == TYPE_6103)) && /* if data<0> set, */ + AC & 010000) dkp_diagmode = 1; /* set diagnostic mode */ + break; + } /* end switch code */ + +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_diagmode) { /* in diagnostic mode? */ + dkp_diagmode = 0; /* reset it */ + if (dtype == TYPE_6099) dkp_ussc = 010002; /* return size bits */ + if (dtype == TYPE_6103) dkp_ussc = 010003; /* for certain types */ + } + else { /* normal mode ... */ + 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 */ -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_diagmode) { /* in diagnostic mode? */ - dkp_diagmode = 0; /* reset it */ - if (dtype == TYPE_6099) dkp_ussc = 010002; /* return size bits */ - if (dtype == TYPE_6103) dkp_ussc = 010003; /* for certain types */ - } - else { /* normal mode ... */ - 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 */ @@ -535,31 +553,38 @@ 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 */ +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 */ + 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; @@ -579,89 +604,100 @@ int32 sx, dx, pa, u; int32 dtype, err, newsect, newsurf; uint32 awc; t_stat rval; -static uint16 tbuf[DKP_NUMWD]; /* transfer buffer */ +static uint16 tbuf[DKP_NUMWD]; /* transfer buffer */ rval = SCPE_OK; -dtype = GET_DTYPE (uptr->flags); /* get drive type */ -if (dkp_diagmode) { /* diagnostic mode? */ - dkp_sta = (dkp_sta | STA_DONE); /* Set error bit only */ - 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 SCPE_OK; /* do not do function */ - } -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; } +dtype = GET_DTYPE (uptr->flags); /* get drive type */ +if (dkp_diagmode) { /* diagnostic mode? */ + dkp_sta = (dkp_sta | STA_DONE); /* Set error bit only */ + 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 SCPE_OK; /* do not do function */ + } +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? */ +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 */ + 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? */ +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 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 */ +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 */ + 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 (dkp_map, (dkp_ma & AMASK)); - if (MEM_ADDR_OK (pa)) M[pa] = tbuf[dx]; - dkp_ma = (dkp_ma + 1) & AMASK; } } } + 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 (dkp_map, (dkp_ma & AMASK)); + 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 (dkp_map, (dkp_ma & AMASK)); - 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 (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 (dkp_map, (dkp_ma & AMASK)); + 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); + if (err != 0) { + perror ("DKP I/O error"); + clearerr (uptr->fileref); + rval = SCPE_IOERR; + } - 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 */ + 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 */ +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) @@ -669,16 +705,17 @@ 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 */ +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 */ -dkp_diagmode = 0; /* clear diagnostic mode */ +dkp_fccy = dkp_ussc = dkp_ma = dkp_sta = 0; /* clear registers */ +dkp_diagmode = 0; /* clear diagnostic mode */ dkp_map = 0; -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; } +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; } @@ -689,15 +726,17 @@ t_stat dkp_attach (UNIT *uptr, char *cptr) int32 i, p; t_stat r; -uptr->capac = drv_tab[GET_DTYPE (uptr->flags)].size; /* restore capac */ -r = attach_unit (uptr, cptr); /* attach */ +uptr->capac = drv_tab[GET_DTYPE (uptr->flags)].size; /* restore capac */ +r = attach_unit (uptr, cptr); /* attach */ if ((r != SCPE_OK) || !(uptr->flags & UNIT_AUTO)) return r; if ((p = sim_fsize (uptr->fileref)) == 0) return SCPE_OK; /* get file size */ for (i = 0; drv_tab[i].sect != 0; i++) { - if (p <= (drv_tab[i].size * (int32) sizeof (uint16))) { - uptr->flags = (uptr->flags & ~UNIT_DTYPE) | (i << UNIT_V_DTYPE); - uptr->capac = drv_tab[i].size; - return SCPE_OK; } } + if (p <= (drv_tab[i].size * (int32) sizeof (uint16))) { + uptr->flags = (uptr->flags & ~UNIT_DTYPE) | (i << UNIT_V_DTYPE); + uptr->capac = drv_tab[i].size; + return SCPE_OK; + } + } return SCPE_OK; } @@ -709,37 +748,37 @@ 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)) +#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[] = { - 0060233, /* NIOC 0,DKP ; clear disk */ - 0020420, /* LDA 0,USSC ; unit, sfc, sec, cnt */ - 0063033, /* DOC 0,DKP ; select disk */ - 0020417, /* LDA 0,SEKCMD ; command, cylinder */ - 0061333, /* DOAP 0,DKP ; start seek */ - 0024415, /* LDA 1,SEKDN */ - 0060433, /* DIA 0,DKP ; get status */ - 0123415, /* AND# 1,0,SZR ; skip if done */ - 0000776, /* JMP .-2 */ - 0102400, /* SUB 0,0 ; mem addr = 0 */ - 0062033, /* DOB 0,DKP */ - 0020411, /* LDA 0,REDCMD ; command, cylinder */ - 0061133, /* DOAS 0,DKP ; start read */ - 0060433, /* DIA 0, DKP ; get status */ - 0101113, /* MOVL# 0,0,SNC ; skip if done */ - 0000776, /* JMP .-2 */ - 0000377, /* JMP 377 */ - 0000016, /* USSC: 0.B1+0.B7+0.B11+16 */ - 0175000, /* SEKCMD: 175000 */ - 0074000, /* SEKDN: 074000 */ - 0174000 /* REDCMD: 174000 */ -}; + 0060233, /* NIOC 0,DKP ; clear disk */ + 0020420, /* LDA 0,USSC ; unit, sfc, sec, cnt */ + 0063033, /* DOC 0,DKP ; select disk */ + 0020417, /* LDA 0,SEKCMD ; command, cylinder */ + 0061333, /* DOAP 0,DKP ; start seek */ + 0024415, /* LDA 1,SEKDN */ + 0060433, /* DIA 0,DKP ; get status */ + 0123415, /* AND# 1,0,SZR ; skip if done */ + 0000776, /* JMP .-2 */ + 0102400, /* SUB 0,0 ; mem addr = 0 */ + 0062033, /* DOB 0,DKP */ + 0020411, /* LDA 0,REDCMD ; command, cylinder */ + 0061133, /* DOAS 0,DKP ; start read */ + 0060433, /* DIA 0, DKP ; get status */ + 0101113, /* MOVL# 0,0,SNC ; skip if done */ + 0000776, /* JMP .-2 */ + 0000377, /* JMP 377 */ + 0000016, /* USSC: 0.B1+0.B7+0.B11+16 */ + 0175000, /* SEKCMD: 175000 */ + 0074000, /* SEKDN: 074000 */ + 0174000 /* REDCMD: 174000 */ + }; t_stat dkp_boot (int32 unitno, DEVICE *dptr) { diff --git a/NOVA/nova_doc.txt b/NOVA/nova_doc.txt index dae5a064..ed1527b3 100644 --- a/NOVA/nova_doc.txt +++ b/NOVA/nova_doc.txt @@ -7,8 +7,8 @@ Date: 15-Nov-2004 The following copyright notice applies to both the SIMH source and binary: - Original code published in 1993-2004, written by Robert M Supnik - Copyright (c) 1993-2004, Robert M Supnik + Original code published in 1993-2005, written by Robert M Supnik + Copyright (c) 1993-2005, 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"), @@ -27,8 +27,8 @@ The following copyright notice applies to both the SIMH source and binary: 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 + 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. diff --git a/NOVA/nova_dsk.c b/NOVA/nova_dsk.c index e75ec25d..db680742 100644 --- a/NOVA/nova_dsk.c +++ b/NOVA/nova_dsk.c @@ -1,6 +1,6 @@ /* nova_dsk.c: 4019 fixed head disk simulator - Copyright (c) 1993-2004, Robert M. Supnik + Copyright (c) 1993-2005, 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"), @@ -19,23 +19,23 @@ 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 + 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 + dsk fixed head disk - 04-Jan-04 RMS Changed sim_fsize calling sequence - 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 + 04-Jan-04 RMS Changed sim_fsize calling sequence + 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. @@ -44,61 +44,62 @@ #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) +#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)) +#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 */ +#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) +#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 }; + 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))) -#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 */ +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); @@ -110,49 +111,53 @@ 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 + 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) }; +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 } }; + { 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 } }; + { 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 }; - + "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) @@ -160,47 +165,56 @@ 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 */ +switch (code) { /* decode IR<5:7> */ -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 */ + case ioDIA: /* DIA */ + rval = dsk_stat & DSKS_ALLERR; /* read status */ + break; -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; } + case ioDOA: /* DOA */ + dsk_da = AC & DSK_AMASK; /* save disk addr */ + break; -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 */ + 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) @@ -208,58 +222,63 @@ t_stat dsk_svc (UNIT *uptr) int32 i, da, pa; int16 *fbuf = uptr->filebuf; -dev_busy = dev_busy & ~INT_DSK; /* clear busy */ -dev_done = dev_done | INT_DSK; /* set done */ +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); } +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] = fbuf[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 */ - fbuf[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; } +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] = fbuf[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 */ + fbuf[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 */ +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 */ +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)) +#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 */ -}; + 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) { @@ -282,11 +301,11 @@ t_stat r; r = attach_unit (uptr, cptr); if (r != SCPE_OK) return r; if ((uptr->flags & UNIT_AUTO) && (sz = sim_fsize (uptr->fileref))) { - 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 */ + 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 SCPE_OK; } diff --git a/NOVA/nova_lp.c b/NOVA/nova_lp.c index 93f2d737..d155e07f 100644 --- a/NOVA/nova_lp.c +++ b/NOVA/nova_lp.c @@ -1,6 +1,6 @@ /* nova_lp.c: NOVA line printer simulator - Copyright (c) 1993-2004, Robert M. Supnik + Copyright (c) 1993-2005, 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"), @@ -19,21 +19,21 @@ 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 + 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 + lpt line printer - 25-Apr-03 RMS Revised for extended file support - 30-May-02 RMS Widened POS to 32b + 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_stopioe = 0; /* stop on error */ int32 lpt (int32 pulse, int32 code, int32 AC); t_stat lpt_svc (UNIT *uptr); @@ -41,56 +41,63 @@ t_stat lpt_reset (DEVICE *dptr); /* LPT data structures - lpt_dev LPT device descriptor - lpt_unit LPT unit descriptor - lpt_reg LPT register list + 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 }; + 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 } }; + { 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 }; - + "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 */ +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; } @@ -98,15 +105,16 @@ return 0; t_stat lpt_svc (UNIT *uptr) { -dev_busy = dev_busy & ~INT_LPT; /* clear busy */ -dev_done = dev_done | INT_LPT; /* set done */ +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 ((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; } + perror ("LPT I/O error"); + clearerr (lpt_unit.fileref); + return SCPE_IOERR; + } lpt_unit.pos = lpt_unit.pos + 1; return SCPE_OK; } @@ -116,9 +124,9 @@ return SCPE_OK; 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 */ +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 */ +sim_cancel (&lpt_unit); /* deactivate unit */ return SCPE_OK; } diff --git a/NOVA/nova_mta.c b/NOVA/nova_mta.c index c20ceb67..0a4f03ae 100644 --- a/NOVA/nova_mta.c +++ b/NOVA/nova_mta.c @@ -19,46 +19,47 @@ 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 + 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 + mta magnetic tape - 18-Mar-05 RMS Added attached test to detach routine - 22-Nov-03 CEO DIB returns # records skipped after space fwd - 22-Nov-03 CEO Removed cancel of tape events in IORST - 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 + 16-Aug-05 RMS Fixed C++ declaration and cast problems + 18-Mar-05 RMS Added attached test to detach routine + 22-Nov-03 CEO DIB returns # records skipped after space fwd + 22-Nov-03 CEO Removed cancel of tape events in IORST + 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 + 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 @@ -68,95 +69,95 @@ #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) +#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) +#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 */ +#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_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 */ -#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 */ +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); @@ -170,62 +171,67 @@ 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 */ +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 }; + 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 + 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) } }; + { 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 } }; + { 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 } }; + { 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 }; - + "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) @@ -234,73 +240,88 @@ 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 */ +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 */ + +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 */ -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 @@ -314,125 +335,130 @@ 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 */ +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->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 */ +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_CMODE: /* controller mode */ + mta_ep = mta_cu & CU_EP; + break; -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_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; -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_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_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_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; -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_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_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); - mta_ma = mta_wc; /* Word count = # records */ - 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_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); - mta_ma = mta_wc; /* Word count = # records */ - 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); + mta_ma = mta_wc; /* word count = # records */ + break; -default: /* reserved */ - mta_sta = mta_sta | STA_ILL; - mta_upddsta (uptr, uptr->USTAT | STA_RDY); - break; } /* end case */ + 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); + mta_ma = mta_wc; /* word count = # records */ + break; -mta_updcsta (uptr); /* update status */ -dev_busy = dev_busy & ~INT_MTA; /* clear busy */ -dev_done = dev_done | INT_MTA; /* set done */ + 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 */ +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; + (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; @@ -440,19 +466,21 @@ return mta_sta; /* Update drive status */ -void mta_upddsta (UNIT *uptr, int32 newsta) /* 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 ((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 */ +/* 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; } @@ -461,41 +489,51 @@ return; 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; } + + 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) @@ -503,29 +541,30 @@ 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 */ +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_cu = mta_wc = mta_ma = mta_sta = 0; /* clear registers */ mta_ep = 0; /* AOS Installer does an IORST after a tape rewind command but before it can be serviced, yet expects the tape to have been rewound */ -for (u = 0; u < MTA_NUMDR; u++) { /* loop thru units */ - uptr = mta_dev.units + u; - if (sim_is_active (uptr) && /* active and */ - (uptr->flags & STA_REW)) /* rewinding? */ - sim_tape_rewind (uptr); /* update tape */ - sim_tape_reset (uptr); /* clear pos flag */ - sim_cancel (uptr); /* cancel activity */ - if (uptr->flags & UNIT_ATT) uptr->USTAT = STA_RDY | +for (u = 0; u < MTA_NUMDR; u++) { /* loop thru units */ + uptr = mta_dev.units + u; + if (sim_is_active (uptr) && /* active and */ + (uptr->flags & STA_REW)) /* rewinding? */ + sim_tape_rewind (uptr); /* update tape */ + 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)); + else uptr->USTAT = 0; + } +mta_updcsta (&mta_unit[0]); /* update status */ +if (mtxb == NULL) mtxb = (uint8 *) calloc (MTA_MAXFR, sizeof (uint8)); if (mtxb == NULL) return SCPE_MEM; return SCPE_OK; } @@ -539,7 +578,7 @@ 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)); + (sim_tape_wrp (uptr)? STA_WLK: 0)); return r; } @@ -547,7 +586,7 @@ return r; t_stat mta_detach (UNIT* uptr) { -if (!(uptr->flags & UNIT_ATT)) return SCPE_OK; /* attached? */ +if (!(uptr->flags & UNIT_ATT)) return SCPE_OK; /* attached? */ if (!sim_is_active (uptr)) mta_upddsta (uptr, 0); return sim_tape_detach (uptr); } @@ -557,11 +596,11 @@ return sim_tape_detach (uptr); 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); + mta_upddsta (uptr, uptr->USTAT | STA_WLK); else mta_upddsta (uptr, uptr->USTAT & ~STA_WLK); return SCPE_OK; } - + /* Bootstrap routine */ #define BOOT_START 02000 @@ -569,25 +608,25 @@ return SCPE_OK; #define BOOT_LEN (sizeof (boot_rom) / sizeof (int)) static const int32 boot_rom[] = { - 0060222, /* NIOC 0,MTA ; clear disk */ - 0020417, /* LDA 0,UNIT ; unit */ - 0024417, /* LDA 1,REWIND ; cmd */ - 0107000, /* ADD 0,1 ; cmd + unit */ - 0065122, /* DOAS 1,MTA ; start rewind */ - 0070422, /* DIA 2,MTA ; get status */ - 0151213, /* MOVR# 2,2,SNC ; skip if done */ - 0000776, /* JMP .-2 */ - 0126400, /* SUB 1,1 ; ma, wc = 0 */ - 0066022, /* DOB 1,MTA */ - 0067022, /* DOC 1,MTA */ - 0061122, /* DOAS 0,MTA ; start read */ - 0070422, /* DIA 2,MTA ; get status */ - 0151213, /* MOVR# 2,2,SNC ; skip if done */ - 0000776, /* JMP .-2 */ - 0000377, /* JMP 377 */ - 0000000, /* UNIT: */ - 0000010 /* REWIND: 10 */ -}; + 0060222, /* NIOC 0,MTA ; clear disk */ + 0020417, /* LDA 0,UNIT ; unit */ + 0024417, /* LDA 1,REWIND ; cmd */ + 0107000, /* ADD 0,1 ; cmd + unit */ + 0065122, /* DOAS 1,MTA ; start rewind */ + 0070422, /* DIA 2,MTA ; get status */ + 0151213, /* MOVR# 2,2,SNC ; skip if done */ + 0000776, /* JMP .-2 */ + 0126400, /* SUB 1,1 ; ma, wc = 0 */ + 0066022, /* DOB 1,MTA */ + 0067022, /* DOC 1,MTA */ + 0061122, /* DOAS 0,MTA ; start read */ + 0070422, /* DIA 2,MTA ; get status */ + 0151213, /* MOVR# 2,2,SNC ; skip if done */ + 0000776, /* JMP .-2 */ + 0000377, /* JMP 377 */ + 0000000, /* UNIT: */ + 0000010 /* REWIND: 10 */ + }; t_stat mta_boot (int32 unitno, DEVICE *dptr) { diff --git a/NOVA/nova_plt.c b/NOVA/nova_plt.c index c0efb0df..88704d7f 100644 --- a/NOVA/nova_plt.c +++ b/NOVA/nova_plt.c @@ -1,6 +1,6 @@ /* nova_plt.c: NOVA plotter simulator - Copyright (c) 2000-2004, Robert M. Supnik + Copyright (c) 2000-2005, 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 @@ -20,78 +20,85 @@ 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 + 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 + 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 + 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 */ +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 + 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 }; + 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 } }; + { 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 }; - + "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 */ +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; } @@ -99,15 +106,16 @@ return 0; t_stat plt_svc (UNIT *uptr) { -dev_busy = dev_busy & ~INT_PLT; /* clear busy */ -dev_done = dev_done | INT_PLT; /* set done */ +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 ((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; } + perror ("PLT I/O error"); + clearerr (plt_unit.fileref); + return SCPE_IOERR; + } plt_unit.pos = plt_unit.pos + 1; return SCPE_OK; } @@ -117,9 +125,9 @@ return SCPE_OK; 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 */ +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 */ +sim_cancel (&plt_unit); /* deactivate unit */ return SCPE_OK; } diff --git a/NOVA/nova_pt.c b/NOVA/nova_pt.c index 38bc441e..9559ea75 100644 --- a/NOVA/nova_pt.c +++ b/NOVA/nova_pt.c @@ -1,6 +1,6 @@ /* nova_pt.c: NOVA paper tape read/punch simulator - Copyright (c) 1993-2004, Robert M. Supnik + Copyright (c) 1993-2005, 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"), @@ -19,24 +19,24 @@ 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 + 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 + 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 + 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_stopioe = 0, ptp_stopioe = 0; /* stop on error */ int32 ptr (int32 pulse, int32 code, int32 AC); int32 ptp (int32 pulse, int32 code, int32 AC); @@ -44,68 +44,74 @@ 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 + 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 }; + 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 } }; + { 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 }; + "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 + 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 }; + 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 } }; + { 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 }; - + "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) @@ -113,19 +119,23 @@ 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 */ +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; } @@ -135,17 +145,19 @@ 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 */ +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; @@ -157,31 +169,35 @@ return SCPE_OK; 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 */ +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 */ +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 */ +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; } @@ -189,15 +205,16 @@ return 0; t_stat ptp_svc (UNIT *uptr) { -dev_busy = dev_busy & ~INT_PTP; /* clear busy */ -dev_done = dev_done | INT_PTP; /* set done */ +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 ((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; } + perror ("PTP I/O error"); + clearerr (ptp_unit.fileref); + return SCPE_IOERR; + } ptp_unit.pos = ptp_unit.pos + 1; return SCPE_OK; } @@ -207,9 +224,9 @@ return SCPE_OK; 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 */ +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 */ +sim_cancel (&ptp_unit); /* deactivate unit */ return SCPE_OK; } diff --git a/NOVA/nova_qty.c b/NOVA/nova_qty.c index e92b2997..258fbeb6 100644 --- a/NOVA/nova_qty.c +++ b/NOVA/nova_qty.c @@ -1,6 +1,6 @@ /* nova_qty.c: NOVA multiplexor (QTY/ALM) simulator - Copyright (c) 2000-2003, Robert M. Supnik + Copyright (c) 2000-2005, 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 @@ -20,75 +20,75 @@ 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 + 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. - qty multiplexor: QTY = 4060, ALM = 42xx + qty multiplexor: QTY = 4060, ALM = 42xx - 25-Mar-04 RMS Updated for V3.2 - 12-Jan-04 BKR Initial release - includes both original DG "quad" multiplexor (QTY) - and later Asynchronous Line Multiplexor (ALM) support. + 25-Mar-04 RMS Updated for V3.2 + 12-Jan-04 BKR Initial release + includes both original DG "quad" multiplexor (QTY) + and later Asynchronous Line Multiplexor (ALM) support. */ /*----------------------------------------------------------------------*/ -/* QTY [4060-compatible] multiplexor */ +/* QTY [4060-compatible] multiplexor */ /*----------------------------------------------------------------------*/ /* - * Emulate the DG 4060 "quad" (QTY) serial port multiplexor. DG modem - * control is not supported in this revision due to its obtuse nature - * of using a separate [semi-secret] device MDM which is actually part - * of the DG 4026/4027 multiplexor hardware(!). - * (Full modem support is provided in the ALM driver.) + * Emulate the DG 4060 "quad" (QTY) serial port multiplexor. DG modem + * control is not supported in this revision due to its obtuse nature + * of using a separate [semi-secret] device MDM which is actually part + * of the DG 4026/4027 multiplexor hardware(!). + * (Full modem support is provided in the ALM driver.) * * - * 4060 Hardware + * 4060 Hardware * - * device code: 030 [primary], - * 070 [secondary] - * interrupt mask: B14 [000002] - * ASM mnemonic: QTY + * device code: 030 [primary], + * 070 [secondary] + * interrupt mask: B14 [000002] + * ASM mnemonic: QTY * * - * 4060 Input/Output Word Format: + * 4060 Input/Output Word Format: * * _________________________________________________________________ * | RI| TI| channel | character | * ----+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ - * 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 + * 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 * * - * RI - receiver interrupt - * TI - transmitter interrupt - * channel - channel number, 0 - 63. - * character- character (valid if receiver interrupt, undefined if transmitter) + * RI - receiver interrupt + * TI - transmitter interrupt + * channel - channel number, 0 - 63. + * character- character (valid if receiver interrupt, undefined if transmitter) * - * Notes: + * Notes: * - * Maximum 64 lines supported. - * DONE set whenever any received character fully assembled and ready, - * or when any output character transmitted and line is ready - * to accept next output character. - * BUSY set whenever output character is being sent on any line. - * Note that early 4060s did NOT have a busy flag! - * IORST clears device Done, no other user instruction does. - * IORST clears each line's individual R.I. and T.I. + * Maximum 64 lines supported. + * DONE set whenever any received character fully assembled and ready, + * or when any output character transmitted and line is ready + * to accept next output character. + * BUSY set whenever output character is being sent on any line. + * Note that early 4060s did NOT have a busy flag! + * IORST clears device Done, no other user instruction does. + * IORST clears each line's individual R.I. and T.I. * * - * Instructions: + * Instructions: * - * DIA get multiplexor status word [format defined above] - * DOA send character to QTY line [format defined above, RI & SI ] - * DIB [returns backplane bus noise] - * DOB clear QTY line - * DIC [returns backplace bus noise] - * DOC - * 'C' clears global done, then checks for RI and TI; - * 'P' - * 'S' + * DIA get multiplexor status word [format defined above] + * DOA send character to QTY line [format defined above, RI & SI ] + * DIB [returns backplane bus noise] + * DOB clear QTY line + * DIC [returns backplace bus noise] + * DOC + * 'C' clears global done, then checks for RI and TI; + * 'P' + * 'S' */ @@ -98,501 +98,499 @@ #include "sim_tmxr.h" -#define UNIT_V_8B (UNIT_V_UF + 0) /* 8b output */ -#define UNIT_8B (1 << UNIT_V_8B) +#define UNIT_V_8B (UNIT_V_UF + 0) /* 8b output */ +#define UNIT_8B (1 << UNIT_V_8B) -extern int32 int_req, dev_busy, dev_done, dev_disable ; -extern int32 sim_switches ; -extern FILE * sim_log ; -extern int32 tmxr_poll ; /* calibrated delay */ +extern int32 int_req, dev_busy, dev_done, dev_disable ; +extern int32 sim_switches ; +extern FILE * sim_log ; +extern int32 tmxr_poll ; /* calibrated delay */ -t_stat qty_summary ( FILE * st, UNIT * uptr, int32 val, void * desc ) ; -t_stat qty_show ( FILE * st, UNIT * uptr, int32 val, void * desc ) ; -t_stat qty_setnl ( UNIT * uptr, int32 val, char * cptr, void * desc ) ; +t_stat qty_summary ( FILE * st, UNIT * uptr, int32 val, void * desc ) ; +t_stat qty_show ( FILE * st, UNIT * uptr, int32 val, void * desc ) ; +t_stat qty_setnl ( UNIT * uptr, int32 val, char * cptr, void * desc ) ; -t_stat qty_attach ( UNIT * uptr, char * cptr ) ; -t_stat qty_detach ( UNIT * uptr ) ; -t_stat qty_reset ( DEVICE * dptr ) ; -t_stat qty_svc ( UNIT * uptr ) ; -int32 qty ( int32 pulse, int32 code, int32 AC ) ; +t_stat qty_attach ( UNIT * uptr, char * cptr ) ; +t_stat qty_detach ( UNIT * uptr ) ; +t_stat qty_reset ( DEVICE * dptr ) ; +t_stat qty_svc ( UNIT * uptr ) ; +int32 qty ( int32 pulse, int32 code, int32 AC ) ; -t_stat alm_reset ( DEVICE * dptr ) ; -t_stat alm_svc ( UNIT * uptr ) ; -int32 alm ( int32 pulse, int32 code, int32 AC ) ; +t_stat alm_reset ( DEVICE * dptr ) ; +t_stat alm_svc ( UNIT * uptr ) ; +int32 alm ( int32 pulse, int32 code, int32 AC ) ; -DEVICE alm_dev ; +DEVICE alm_dev ; -#define QTY_MAX 64 /* max number of QTY lines - hardware */ +#define QTY_MAX 64 /* max number of QTY lines - hardware */ -int32 qty_brkio = SCPE_OK ; /* default I/O status code */ -int32 qty_max = QTY_MAX ; /* max # QTY lines - user */ - /* controllable */ -int32 qty_mdm = 0 ; /* QTY modem control active? */ -int32 qty_auto = 0 ; /* QTY auto disconnect active? */ -int32 qty_polls = 0 ; /* total 'qty_svc' polls */ +int32 qty_brkio = SCPE_OK ; /* default I/O status code */ +int32 qty_max = QTY_MAX ; /* max # QTY lines - user */ + /* controllable */ +int32 qty_mdm = 0 ; /* QTY modem control active? */ +int32 qty_auto = 0 ; /* QTY auto disconnect active? */ +int32 qty_polls = 0 ; /* total 'qty_svc' polls */ -TMLN qty_ldsc[ QTY_MAX ] = { 0 } ; /* QTY line descriptors */ -TMXR qty_desc = { QTY_MAX, 0, 0, qty_ldsc } ; /* mux descriptor */ -int32 qty_status[ QTY_MAX ] = { 0 } ; /* QTY line status */ - /* (must be at least 32 bits) */ -int32 qty_tx_chr[ QTY_MAX ] = { 0 } ; /* QTY line output character */ +TMLN qty_ldsc[ QTY_MAX ] = { 0 } ; /* QTY line descriptors */ +TMXR qty_desc = { QTY_MAX, 0, 0, qty_ldsc } ; /* mux descriptor */ +int32 qty_status[ QTY_MAX ] = { 0 } ; /* QTY line status */ + /* (must be at least 32 bits) */ +int32 qty_tx_chr[ QTY_MAX ] = { 0 } ; /* QTY line output character */ /* QTY data structures - qty_dev QTY device descriptor - qty_unit QTY unit descriptor - qty_reg QTY register list + qty_dev QTY device descriptor + qty_unit QTY unit descriptor + qty_reg QTY register list */ -DIB qty_dib = { DEV_QTY, INT_QTY, PI_QTY, &qty } ; +DIB qty_dib = { DEV_QTY, INT_QTY, PI_QTY, &qty } ; -UNIT qty_unit = - { - UDATA (&qty_svc, (UNIT_ATTABLE), 0) - } ; +UNIT qty_unit = + { + UDATA (&qty_svc, (UNIT_ATTABLE), 0) + } ; -REG qty_nlreg = { DRDATA (NLINES, qty_desc.lines, 7), PV_LEFT }; +REG qty_nlreg = { DRDATA (NLINES, qty_desc.lines, 7), PV_LEFT }; -REG qty_reg[] = /* ('alm_reg' should be similar to this except for device code related items) */ - { - { ORDATA (BUF, qty_unit.buf, 8) }, - { FLDATA (BUSY, dev_busy, INT_V_QTY) }, - { FLDATA (DONE, dev_done, INT_V_QTY) }, - { FLDATA (DISABLE, dev_disable, INT_V_QTY) }, - { FLDATA (INT, int_req, INT_V_QTY) }, +REG qty_reg[] = /* ('alm_reg' should be similar to this except for device code related items) */ + { + { ORDATA (BUF, qty_unit.buf, 8) }, + { FLDATA (BUSY, dev_busy, INT_V_QTY) }, + { FLDATA (DONE, dev_done, INT_V_QTY) }, + { FLDATA (DISABLE, dev_disable, INT_V_QTY) }, + { FLDATA (INT, int_req, INT_V_QTY) }, - { FLDATA (MDMCTL, qty_mdm, 0) }, - { FLDATA (AUTODS, qty_auto, 0) }, - { DRDATA (POLLS, qty_polls, 32) }, - { NULL } - } ; + { FLDATA (MDMCTL, qty_mdm, 0) }, + { FLDATA (AUTODS, qty_auto, 0) }, + { DRDATA (POLLS, qty_polls, 32) }, + { NULL } + } ; -MTAB qty_mod[] = - { - { UNIT_8B, 0, "7b", "7B", NULL }, - { UNIT_8B, UNIT_8B, "8b", "8B", NULL }, - { MTAB_XTD | MTAB_VDV, 1, NULL, "DISCONNECT", - &tmxr_dscln, NULL, &qty_desc }, - { UNIT_ATT, UNIT_ATT, "connections", NULL, NULL, &qty_summary }, - { MTAB_XTD | MTAB_VDV | MTAB_NMO, 1, "CONNECTIONS", NULL, - NULL, &qty_show, NULL }, - { MTAB_XTD | MTAB_VDV | MTAB_NMO, 0, "STATISTICS", NULL, - NULL, &qty_show, NULL }, - { MTAB_XTD | MTAB_VDV | MTAB_VAL, 0, "lines", "LINES", - &qty_setnl, NULL, &qty_nlreg }, - { 0 } - } ; +MTAB qty_mod[] = + { + { UNIT_8B, 0, "7b", "7B", NULL }, + { UNIT_8B, UNIT_8B, "8b", "8B", NULL }, + { MTAB_XTD | MTAB_VDV, 1, NULL, "DISCONNECT", + &tmxr_dscln, NULL, &qty_desc }, + { UNIT_ATT, UNIT_ATT, "connections", NULL, NULL, &qty_summary }, + { MTAB_XTD | MTAB_VDV | MTAB_NMO, 1, "CONNECTIONS", NULL, + NULL, &qty_show, NULL }, + { MTAB_XTD | MTAB_VDV | MTAB_NMO, 0, "STATISTICS", NULL, + NULL, &qty_show, NULL }, + { MTAB_XTD | MTAB_VDV | MTAB_VAL, 0, "lines", "LINES", + &qty_setnl, NULL, &qty_nlreg }, + { 0 } + } ; -DEVICE qty_dev = - { - "QTY", &qty_unit, qty_reg, qty_mod, - 1, 10, 31, 1, 8, 8, - NULL, NULL, &qty_reset, - NULL, &qty_attach, &qty_detach, - &qty_dib, (DEV_DISABLE | DEV_DIS | DEV_NET) - }; +DEVICE qty_dev = + { + "QTY", &qty_unit, qty_reg, qty_mod, + 1, 10, 31, 1, 8, 8, + NULL, NULL, &qty_reset, + NULL, &qty_attach, &qty_detach, + &qty_dib, (DEV_DISABLE | DEV_DIS | DEV_NET) + }; - /* */ - /* (need to mask off non-interrupt bit devices) */ + /* */ + /* (need to mask off non-interrupt bit devices) */ -#define DEV_SET_BUSY( dibp ) dev_busy = dev_busy | ( (dibp)->mask ) ; -#define DEV_CLEAR_BUSY( dibp ) dev_busy = dev_busy & ~( (dibp)->mask ) ; -#define DEV_SET_DONE( dibp ) dev_done = dev_done | ( (dibp)->mask ) ; int_req = int_req & ~( (dibp)->mask ) ; -#define DEV_CLEAR_DONE( dibp ) dev_done = dev_done & ~( (dibp)->mask ) ; int_req = int_req & ~( (dibp)->mask ) ; -#define DEV_UPDATE_INTR int_req = (int_req & ~INT_DEV) | (dev_done & ~dev_disable) ; +#define DEV_SET_BUSY( dibp ) dev_busy = dev_busy | ( (dibp)->mask ) ; +#define DEV_CLEAR_BUSY( dibp ) dev_busy = dev_busy & ~( (dibp)->mask ) ; +#define DEV_SET_DONE( dibp ) dev_done = dev_done | ( (dibp)->mask ) ; int_req = int_req & ~( (dibp)->mask ) ; +#define DEV_CLEAR_DONE( dibp ) dev_done = dev_done & ~( (dibp)->mask ) ; int_req = int_req & ~( (dibp)->mask ) ; +#define DEV_UPDATE_INTR int_req = (int_req & ~INT_DEV) | (dev_done & ~dev_disable) ; -#define DG_RETURN( status, data ) (int32)(((status) << IOT_V_REASON) | ((data) & 0x0FFFF) ) +#define DG_RETURN( status, data ) (int32)(((status) << IOT_V_REASON) | ((data) & 0x0FFFF) ) /* - * QTY_S_xxx QTY device status reference - * QTY_L_xxx QTY line status word reference (qty_status[]) + * QTY_S_xxx QTY device status reference + * QTY_L_xxx QTY line status word reference (qty_status[]) */ - /*----------------------------------------------*/ - /* QTY device status */ - /*----------------------------------------------*/ + /*----------------------------------------------*/ + /* QTY device status */ + /*----------------------------------------------*/ -#define QTY_S_RI 0x8000 /* Receiver Interrupt */ -#define QTY_S_TI 0x4000 /* Transmitter interrupt */ -#define QTY_S_LMASK 0x3F00 /* line mask */ -#define QTY_S_DMASK 0x00FF /* data mask (received char) */ +#define QTY_S_RI 0x8000 /* Receiver Interrupt */ +#define QTY_S_TI 0x4000 /* Transmitter interrupt */ +#define QTY_S_LMASK 0x3F00 /* line mask */ +#define QTY_S_DMASK 0x00FF /* data mask (received char) */ -#define QTY_MASTER_ACTIVE( desc ) ( (desc)->master ) +#define QTY_MASTER_ACTIVE( desc ) ( (desc)->master ) -#define QTY_LINE_EXTRACT( x ) (((x) & QTY_S_LMASK) >> 8) +#define QTY_LINE_EXTRACT( x ) (((x) & QTY_S_LMASK) >> 8) -#define QTY_LINE_TX_CHAR( line ) qty_tx_chr[ ((line) % QTY_MAX) ] -#define QTY_LINE_RX_CHAR( line ) (qty_status[ (line) ] & QTY_S_DMASK) -#define QTY_UNIT_ACTIVE( unitp ) ( (unitp)->conn ) +#define QTY_LINE_TX_CHAR( line ) qty_tx_chr[ ((line) % QTY_MAX) ] +#define QTY_LINE_RX_CHAR( line ) (qty_status[ (line) ] & QTY_S_DMASK) +#define QTY_UNIT_ACTIVE( unitp ) ( (unitp)->conn ) -#define QTY_LINE_BITS( line, bits ) qty_status[ (line) ] & bits +#define QTY_LINE_BITS( line, bits ) qty_status[ (line) ] & bits -#define QTY_LINE_SET_BIT( line, bit ) qty_status[ (line) ] |= (bit) ; -#define QTY_LINE_CLEAR_BIT( line, bit ) qty_status[ (line) ] &= ~(bit) ; -#define QTY_LINE_BIT_SET( line, bit ) (qty_status[ (line) ] & (bit)) +#define QTY_LINE_SET_BIT( line, bit ) qty_status[ (line) ] |= (bit) ; +#define QTY_LINE_CLEAR_BIT( line, bit ) qty_status[ (line) ] &= ~(bit) ; +#define QTY_LINE_BIT_SET( line, bit ) (qty_status[ (line) ] & (bit)) + /*----------------------------------------------*/ + /* QTY line status */ + /*----------------------------------------------*/ - /*----------------------------------------------*/ - /* QTY line status */ - /*----------------------------------------------*/ +#define QTY_L_RXE 0x800000 /* receiver enabled? */ +#define QTY_L_RXBZ 0x400000 /* receiver busy? */ +#define QTY_L_RXDN 0x200000 /* receiver done? */ +#define QTY_L_TXE 0x080000 /* transmitter enabled? */ +#define QTY_L_TXBZ 0x040000 /* transmitter busy? */ +#define QTY_L_TXDN 0x020000 /* transmitter done? */ -#define QTY_L_RXE 0x800000 /* receiver enabled? */ -#define QTY_L_RXBZ 0x400000 /* receiver busy? */ -#define QTY_L_RXDN 0x200000 /* receiver done? */ -#define QTY_L_TXE 0x080000 /* transmitter enabled? */ -#define QTY_L_TXBZ 0x040000 /* transmitter busy? */ -#define QTY_L_TXDN 0x020000 /* transmitter done? */ +#define QTY_L_BREAK 0x008000 /* BREAK character received */ +#define QTY_L_RING 0x004000 /* Ring interrupt */ +#define QTY_L_CD 0x002000 /* Carrier Detect */ +#define QTY_L_DTR 0x001000 /* Data Terminal Ready */ + /* <0x00FF = character> */ -#define QTY_L_BREAK 0x008000 /* BREAK character received */ -#define QTY_L_RING 0x004000 /* Ring interrupt */ -#define QTY_L_CD 0x002000 /* Carrier Detect */ -#define QTY_L_DTR 0x001000 /* Data Terminal Ready */ - /* <0x00FF = character> */ - -#define QTY_L_LOOPBK 0x00010000 /* loopback mode */ -#define QTY_L_OVRERR 0x00020000 /* overrun error */ -#define QTY_L_FRMERR 0x00040000 /* framing error */ -#define QTY_L_PARERR 0x00080000 /* parity error */ +#define QTY_L_LOOPBK 0x00010000 /* loopback mode */ +#define QTY_L_OVRERR 0x00020000 /* overrun error */ +#define QTY_L_FRMERR 0x00040000 /* framing error */ +#define QTY_L_PARERR 0x00080000 /* parity error */ /* CD, CTS, DSR, RI */ - /* */ + /* */ -#define QTY_L_MODEM 0x0080 /* */ -#define QTY_L_TELNET 0x0040 /* */ -#define QTY_L_AUTODIS 0x0020 /* */ -#define QTY_L_PARITY -#define QTY_L_7BIT -#define QTY_L_BAUD /* <4 bits> */ +#define QTY_L_MODEM 0x0080 /* */ +#define QTY_L_TELNET 0x0040 /* */ +#define QTY_L_AUTODIS 0x0020 /* */ +#define QTY_L_PARITY +#define QTY_L_7BIT +#define QTY_L_BAUD /* <4 bits> */ -#define QTY_L_DMASK 0x000FF /* data mask (always 8 bits) */ +#define QTY_L_DMASK 0x000FF /* data mask (always 8 bits) */ /* Note: use at least an 'int32' for this guy */ - - /*------------------------------*/ - /* qty_tmxr_putc */ - /*------------------------------*/ + /*------------------------------*/ + /* qty_tmxr_putc */ + /*------------------------------*/ - int qty_tmxr_putc( int line, TMLN * lp, int kar ) - { - int a ; +int qty_tmxr_putc( int line, TMLN * lp, int kar ) + { + int a ; - /*----------------------------------------------*/ - /* Send character to given QTY/telnet line. */ - /* */ - /* enter: line QTY line # */ - /* lp Telnet unit def ptr */ - /* kar character to send */ - /* */ - /* return: SCPE_OK */ - /* SCPE_STALL */ - /* SCPE_LOST */ - /*----------------------------------------------*/ + /*----------------------------------------------*/ + /* Send character to given QTY/telnet line. */ + /* */ + /* enter: line QTY line # */ + /* lp Telnet unit def ptr */ + /* kar character to send */ + /* */ + /* return: SCPE_OK */ + /* SCPE_STALL */ + /* SCPE_LOST */ + /*----------------------------------------------*/ - a = tmxr_putc_ln( lp, kar ) ; - if ( a == SCPE_OK) - { - QTY_LINE_SET_BIT( line, QTY_L_TXDN ) - QTY_LINE_CLEAR_BIT( line, QTY_L_TXBZ ) - } - else if ( a == SCPE_STALL ) - { - /* - (should we try to output the buffer - and then regroup...?) - */ - QTY_LINE_SET_BIT( line, QTY_L_TXBZ ) - QTY_LINE_CLEAR_BIT( line, QTY_L_TXDN ) - QTY_LINE_TX_CHAR( line ) = kar ; - } - else if ( a == SCPE_LOST ) - { - /* no connection - hangup? */ - QTY_LINE_SET_BIT( line, QTY_L_TXBZ ) - QTY_LINE_CLEAR_BIT( line, QTY_L_TXDN ) - QTY_LINE_TX_CHAR( line ) = kar ; - } - return ( a ) ; - } /* end of 'qty_tmxr_putc' */ + a = tmxr_putc_ln( lp, kar ) ; + if ( a == SCPE_OK) + { + QTY_LINE_SET_BIT( line, QTY_L_TXDN ) + QTY_LINE_CLEAR_BIT( line, QTY_L_TXBZ ) + } + else if ( a == SCPE_STALL ) + { + /* + (should we try to output the buffer + and then regroup...?) + */ + QTY_LINE_SET_BIT( line, QTY_L_TXBZ ) + QTY_LINE_CLEAR_BIT( line, QTY_L_TXDN ) + QTY_LINE_TX_CHAR( line ) = kar ; + } + else if ( a == SCPE_LOST ) + { + /* no connection - hangup? */ + QTY_LINE_SET_BIT( line, QTY_L_TXBZ ) + QTY_LINE_CLEAR_BIT( line, QTY_L_TXDN ) + QTY_LINE_TX_CHAR( line ) = kar ; + } + return ( a ) ; + } /* end of 'qty_tmxr_putc' */ - /*----------------------------------------------*/ - /* qty_update_rcvi */ - /*----------------------------------------------*/ + /*----------------------------------------------*/ + /* qty_update_rcvi */ + /*----------------------------------------------*/ - int qty_update_rcvi( TMXR * mp ) - { - int line ; - TMLN * lp ; - int32 datum ; - int changes ; +int qty_update_rcvi( TMXR * mp ) + { + int line ; + TMLN * lp ; + int32 datum ; + int changes ; - /*------------------------------------------------------*/ - /* Search through connected telnet lines for any input */ - /* activity. */ - /* */ - /* enter: mp master telnet qty desc ptr */ - /* */ - /* return: int change count (0 = none seen) */ - /*------------------------------------------------------*/ + /*------------------------------------------------------*/ + /* Search through connected telnet lines for any input */ + /* activity. */ + /* */ + /* enter: mp master telnet qty desc ptr */ + /* */ + /* return: int change count (0 = none seen) */ + /*------------------------------------------------------*/ - for ( changes = line = 0; line < mp->lines; ++line ) - if ( (lp=mp->ldsc+line)->conn && lp->rcve ) - if ( (datum=tmxr_getc_ln(lp)) ) - { - if ( datum & SCPE_BREAK ) - { - /* what should we do here - set QTY_L_BREAK? */ - datum = datum & 0x00FF ; - } - else - { - datum = datum & 0x00FF ; - } - /* */ + for ( changes = line = 0; line < mp->lines; ++line ) + if ( (lp=mp->ldsc+line)->conn && lp->rcve ) + if ( (datum=tmxr_getc_ln(lp)) ) + { + if ( datum & SCPE_BREAK ) + { + /* what should we do here - set QTY_L_BREAK? */ + datum = datum & 0x00FF ; + } + else + { + datum = datum & 0x00FF ; + } + /* */ - QTY_LINE_CLEAR_BIT( line, (QTY_L_RXBZ | QTY_L_DMASK) ) ; - QTY_LINE_SET_BIT( line, (QTY_L_RXDN | datum) ) ; - ++changes ; - } - return ( changes ) ; - } /* end of 'qty_update_rcvi' */ + QTY_LINE_CLEAR_BIT( line, (QTY_L_RXBZ | QTY_L_DMASK) ) ; + QTY_LINE_SET_BIT( line, (QTY_L_RXDN | datum) ) ; + ++changes ; + } + return ( changes ) ; + } /* end of 'qty_update_rcvi' */ - /*----------------------------------------------*/ - /* qty_update_xmti */ - /*----------------------------------------------*/ + /*----------------------------------------------*/ + /* qty_update_xmti */ + /*----------------------------------------------*/ - int qty_update_xmti( TMXR * mp ) - { - int line ; - TMLN * lp ; - int changes ; +int qty_update_xmti( TMXR * mp ) + { + int line ; + TMLN * lp ; + int changes ; - /*------------------------------------------------------*/ - /* Search through connected telnet lines for any de- */ - /* ferred output activity. */ - /* */ - /* enter: mp master telnet qty desc ptr */ - /* */ - /* return: int change count (0 = none seen) */ - /*------------------------------------------------------*/ + /*------------------------------------------------------*/ + /* Search through connected telnet lines for any de- */ + /* ferred output activity. */ + /* */ + /* enter: mp master telnet qty desc ptr */ + /* */ + /* return: int change count (0 = none seen) */ + /*------------------------------------------------------*/ - /* any TX DONE flags set - * any TX BUSY flags set - */ + /* any TX DONE flags set + * any TX BUSY flags set + */ - for ( changes = line = 0; line < mp->lines; ++line ) - if ( QTY_LINE_BIT_SET(line,QTY_L_TXBZ) ) - if ( (lp=mp->ldsc+line)->conn && lp->xmte ) - { - /* why are we busy? buffer was full? */ - /* now some space available - try - * to stuff pending character in - * buffer and free up the world - */ - qty_tmxr_putc( line, lp, QTY_LINE_TX_CHAR(line) ) ; - ++changes ; - } - return ( changes ) ; - } /* end of 'qty_update_xmti' */ + for ( changes = line = 0; line < mp->lines; ++line ) + if ( QTY_LINE_BIT_SET(line,QTY_L_TXBZ) ) + if ( (lp=mp->ldsc+line)->conn && lp->xmte ) + { + /* why are we busy? buffer was full? */ + /* now some space available - try + * to stuff pending character in + * buffer and free up the world + */ + qty_tmxr_putc( line, lp, QTY_LINE_TX_CHAR(line) ) ; + ++changes ; + } + return ( changes ) ; + } /* end of 'qty_update_xmti' */ - /*----------------------------------------------*/ - /* qty_update_status */ - /*----------------------------------------------*/ + /*----------------------------------------------*/ + /* qty_update_status */ + /*----------------------------------------------*/ - int qty_update_status( DIB * dibp, TMXR * tmxr_desc ) - { - int line ; - int status ; - int txbusy ; +int qty_update_status( DIB * dibp, TMXR * tmxr_desc ) + { + int line ; + int status ; + int txbusy ; - /*----------------------------------------------*/ - /* return global device status for current qty */ - /* state. */ - /* */ - /* Receiver interrupts have higher priority */ - /* than transmitter interrupts according to DG */ - /* but this routine could be modified to use */ - /* different priority criteria. */ - /* */ - /* Round-robin polling could also be used in */ - /* some future release rather than starting */ - /* with line 0 each time. */ - /* */ - /* Return of */ - /* first waiting character, else return */ - /* of first finished line */ - /* output, else return 0. */ - /* */ - /* This routine does -not- clear input line */ - /* BZ/DN flags; caller should do this. */ - /* */ - /* Global device done and busy flags are */ - /* updated. */ - /*----------------------------------------------*/ + /*----------------------------------------------*/ + /* return global device status for current qty */ + /* state. */ + /* */ + /* Receiver interrupts have higher priority */ + /* than transmitter interrupts according to DG */ + /* but this routine could be modified to use */ + /* different priority criteria. */ + /* */ + /* Round-robin polling could also be used in */ + /* some future release rather than starting */ + /* with line 0 each time. */ + /* */ + /* Return of */ + /* first waiting character, else return */ + /* of first finished line */ + /* output, else return 0. */ + /* */ + /* This routine does -not- clear input line */ + /* BZ/DN flags; caller should do this. */ + /* */ + /* Global device done and busy flags are */ + /* updated. */ + /*----------------------------------------------*/ - for ( txbusy = status = line = 0 ; line < qty_max ; ++line ) - { - txbusy |= (QTY_LINE_BIT_SET(line,QTY_L_TXBZ)) ; - if ( QTY_LINE_BIT_SET(line,QTY_L_RXDN) ) - { - if ( ! status ) - { - status = QTY_LINE_BITS( line, QTY_S_DMASK ) | QTY_S_RI ; - status = status | (line << 8) ; - } - break ; - } - else if ( QTY_LINE_BIT_SET(line,QTY_L_TXDN) ) - { - if ( ! (status & QTY_S_RI) ) - if ( ! (status & QTY_S_RI) ) - { - status = QTY_S_TI ; - status = status | (line << 8) ; - } - } - } - /* */ - DEV_CLEAR_BUSY( dibp ) - DEV_CLEAR_DONE( dibp ) - if ( txbusy ) - { - DEV_SET_BUSY( dibp ) ; - } - if ( status & (QTY_S_RI | QTY_S_TI) ) - { - DEV_SET_DONE( dibp ) - } - DEV_UPDATE_INTR /* update final intr status */ - return ( status ) ; - } /* end of 'qty_update_status' */ + for ( txbusy = status = line = 0 ; line < qty_max ; ++line ) + { + txbusy |= (QTY_LINE_BIT_SET(line,QTY_L_TXBZ)) ; + if ( QTY_LINE_BIT_SET(line,QTY_L_RXDN) ) + { + if ( ! status ) + { + status = QTY_LINE_BITS( line, QTY_S_DMASK ) | QTY_S_RI ; + status = status | (line << 8) ; + } + break ; + } + else if ( QTY_LINE_BIT_SET(line,QTY_L_TXDN) ) + { + if ( ! (status & QTY_S_RI) ) + if ( ! (status & QTY_S_RI) ) + { + status = QTY_S_TI ; + status = status | (line << 8) ; + } + } + } + /* */ + DEV_CLEAR_BUSY( dibp ) + DEV_CLEAR_DONE( dibp ) + if ( txbusy ) + { + DEV_SET_BUSY( dibp ) ; + } + if ( status & (QTY_S_RI | QTY_S_TI) ) + { + DEV_SET_DONE( dibp ) + } + DEV_UPDATE_INTR /* update final intr status */ + return ( status ) ; + } /* end of 'qty_update_status' */ - /*--------------------------------------------------------------*/ - /* qty_attach */ - /*--------------------------------------------------------------*/ + /*--------------------------------------------------------------*/ + /* qty_attach */ + /*--------------------------------------------------------------*/ t_stat qty_attach( UNIT * unitp, char * cptr ) - { - t_stat r ; - int a ; + { + t_stat r ; + int a ; - /* switches: A auto-disconnect - * M modem control - */ + /* switches: A auto-disconnect + * M modem control + */ - qty_mdm = qty_auto = 0; /* modem ctl off */ - r = tmxr_attach( &qty_desc, unitp, cptr ) ; /* attach QTY */ - if ( r != SCPE_OK ) - { - return ( r ) ; /* error! */ - } - if ( sim_switches & SWMASK('M') ) /* modem control? */ - { - qty_mdm = 1; - printf( "Modem control activated\n" ) ; - if ( sim_log ) fprintf( sim_log, "Modem control activated\n" ) ; - if ( sim_switches & SWMASK ('A') ) /* autodisconnect? */ - { - qty_auto = 1 ; - printf( "Auto disconnect activated\n" ) ; - if ( sim_log ) fprintf( sim_log, "Auto disconnect activated\n" ) ; - } - } - qty_polls = 0 ; - for ( a = 0 ; a < QTY_MAX ; ++a ) - { - /* QTY lines are always enabled - force RX and TX to 'enabled' */ - qty_status[ a ] = (QTY_L_RXE | QTY_L_TXE) ; - } - sim_activate( unitp, tmxr_poll ) ; - return ( SCPE_OK ) ; - } /* end of 'qty_attach' */ + qty_mdm = qty_auto = 0; /* modem ctl off */ + r = tmxr_attach( &qty_desc, unitp, cptr ) ; /* attach QTY */ + if ( r != SCPE_OK ) + { + return ( r ) ; /* error! */ + } + if ( sim_switches & SWMASK('M') ) /* modem control? */ + { + qty_mdm = 1; + printf( "Modem control activated\n" ) ; + if ( sim_log ) fprintf( sim_log, "Modem control activated\n" ) ; + if ( sim_switches & SWMASK ('A') ) /* autodisconnect? */ + { + qty_auto = 1 ; + printf( "Auto disconnect activated\n" ) ; + if ( sim_log ) fprintf( sim_log, "Auto disconnect activated\n" ) ; + } + } + qty_polls = 0 ; + for ( a = 0 ; a < QTY_MAX ; ++a ) + { + /* QTY lines are always enabled - force RX and TX to 'enabled' */ + qty_status[ a ] = (QTY_L_RXE | QTY_L_TXE) ; + } + sim_activate( unitp, tmxr_poll ) ; + return ( SCPE_OK ) ; + } /* end of 'qty_attach' */ - /*--------------------------------------------------------------*/ - /* qty_detach */ - /*--------------------------------------------------------------*/ + /*--------------------------------------------------------------*/ + /* qty_detach */ + /*--------------------------------------------------------------*/ t_stat qty_detach( UNIT * unitp ) - { - sim_cancel( unitp ) ; - return ( tmxr_detach(&qty_desc,unitp) ) ; - } /* end of 'qty_detach' */ + { + sim_cancel( unitp ) ; + return ( tmxr_detach(&qty_desc,unitp) ) ; + } /* end of 'qty_detach' */ - /*--------------------------------------------------------------*/ - /* qty_clear */ - /*--------------------------------------------------------------*/ + /*--------------------------------------------------------------*/ + /* qty_clear */ + /*--------------------------------------------------------------*/ t_stat qty_clear( t_bool flag ) - { - int line ; + { + int line ; - for ( line = 0 ; line < qty_max ; ++line ) - { - qty_ldsc[line].xmte = 0 ; - qty_ldsc[line].rcve = 0 ; - if ( ! qty_ldsc[line].conn ) - { - qty_ldsc[line].xmte = 1 ; /* set xmt enb */ - qty_ldsc[line].rcve = 1 ; /* clr rcv enb */ - } - } - return ( SCPE_OK ) ; - } /* end of 'qty_clear' */ + for ( line = 0 ; line < qty_max ; ++line ) + { + qty_ldsc[line].xmte = 0 ; + qty_ldsc[line].rcve = 0 ; + if ( ! qty_ldsc[line].conn ) + { + qty_ldsc[line].xmte = 1 ; /* set xmt enb */ + qty_ldsc[line].rcve = 1 ; /* clr rcv enb */ + } + } + return ( SCPE_OK ) ; + } /* end of 'qty_clear' */ - /*----------------------------------------------*/ - /* qty_common_reset */ - /*----------------------------------------------*/ + /*----------------------------------------------*/ + /* qty_common_reset */ + /*----------------------------------------------*/ - t_stat qty_common_reset( DIB * dibp, UNIT * unitp, DEVICE * dptr ) - { - if ((dptr->flags & DEV_DIS) == 0) - { - if (dptr == &qty_dev) alm_dev.flags |= DEV_DIS; - else qty_dev.flags |= DEV_DIS; - } - qty_clear( TRUE ) ; - DEV_CLEAR_BUSY( dibp ) /* clear busy */ - DEV_CLEAR_DONE( dibp ) /* clear done, int */ - DEV_UPDATE_INTR - if ( QTY_MASTER_ACTIVE(&qty_desc) ) - { - sim_activate( unitp, tmxr_poll ) ; - } - else - { - sim_cancel( unitp ) ; - } - return ( SCPE_OK ) ; - } /* end of 'qty_common_reset' */ +t_stat qty_common_reset( DIB * dibp, UNIT * unitp, DEVICE * dptr ) + { + if ((dptr->flags & DEV_DIS) == 0) + { + if (dptr == &qty_dev) alm_dev.flags |= DEV_DIS; + else qty_dev.flags |= DEV_DIS; + } + qty_clear( TRUE ) ; + DEV_CLEAR_BUSY( dibp ) /* clear busy */ + DEV_CLEAR_DONE( dibp ) /* clear done, int */ + DEV_UPDATE_INTR + if ( QTY_MASTER_ACTIVE(&qty_desc) ) + { + sim_activate( unitp, tmxr_poll ) ; + } + else + { + sim_cancel( unitp ) ; + } + return ( SCPE_OK ) ; + } /* end of 'qty_common_reset' */ - /*--------------------------------------------------------------*/ - /* qty_reset */ - /*--------------------------------------------------------------*/ + /*--------------------------------------------------------------*/ + /* qty_reset */ + /*--------------------------------------------------------------*/ t_stat qty_reset( DEVICE * dptr ) - { - return ( qty_common_reset(&qty_dib,&qty_unit,dptr) ) ; - } /* end of 'qty_reset' */ + { + return ( qty_common_reset(&qty_dib,&qty_unit,dptr) ) ; + } /* end of 'qty_reset' */ /* Unit service routine @@ -605,526 +603,526 @@ t_stat qty_reset( DEVICE * dptr ) or none of them. */ - /*----------------------------------------------*/ - /* qty_common_svc */ - /*----------------------------------------------*/ + /*----------------------------------------------*/ + /* qty_common_svc */ + /*----------------------------------------------*/ - t_stat qty_common_svc( DIB * dibp, UNIT * unitp ) - { - int line ; - int newln ; - TMLN * tmlnp ; +t_stat qty_common_svc( DIB * dibp, UNIT * unitp ) + { + int line ; + int newln ; + TMLN * tmlnp ; - ++qty_polls ; /* another time 'round the track */ - newln = tmxr_poll_conn( &qty_desc ) ; /* anybody knocking at the door? */ - if ( (newln >= 0) && qty_mdm ) - if ( newln >= qty_max ) - { - return SCPE_IERR; /* WTF - sanity check failed, over? */ - } - else - { - line = newln ; /* handle modem control */ - tmlnp =&qty_ldsc[ line ] ; - tmlnp->rcve = tmlnp->xmte = 1 ; - /* do QTY_LINE_ bit fiddling and state machine - * manipulation with modem control signals - */ - } + ++qty_polls ; /* another time 'round the track */ + newln = tmxr_poll_conn( &qty_desc ) ; /* anybody knocking at the door? */ + if ( (newln >= 0) && qty_mdm ) + if ( newln >= qty_max ) + { + return SCPE_IERR; /* WTF - sanity check failed, over? */ + } + else + { + line = newln ; /* handle modem control */ + tmlnp =&qty_ldsc[ line ] ; + tmlnp->rcve = tmlnp->xmte = 1 ; + /* do QTY_LINE_ bit fiddling and state machine + * manipulation with modem control signals + */ + } - tmxr_poll_rx( &qty_desc ) ; /* poll input */ - qty_update_rcvi( &qty_desc ) ; /* update receiver interrupt status */ + tmxr_poll_rx( &qty_desc ) ; /* poll input */ + qty_update_rcvi( &qty_desc ) ; /* update receiver interrupt status */ - tmxr_poll_tx( &qty_desc ) ; /* poll output */ - qty_update_xmti( &qty_desc ) ; /* update transmitter interrupt status */ + tmxr_poll_tx( &qty_desc ) ; /* poll output */ + qty_update_xmti( &qty_desc ) ; /* update transmitter interrupt status */ - qty_update_status( dibp, &qty_desc ) ;/* update device status */ + qty_update_status( dibp, &qty_desc ) ; /* update device status */ - sim_activate( unitp, tmxr_poll ) ; /* restart the bubble machine */ - return ( SCPE_OK ) ; - } /* end of 'qty_common_svc' */ + sim_activate( unitp, tmxr_poll ) ; /* restart the bubble machine */ + return ( SCPE_OK ) ; + } /* end of 'qty_common_svc' */ - /*--------------------------------------------------------------*/ - /* qty_svc */ - /*--------------------------------------------------------------*/ + /*--------------------------------------------------------------*/ + /* qty_svc */ + /*--------------------------------------------------------------*/ t_stat qty_svc( UNIT * uptr ) - { - return ( qty_common_svc(&qty_dib,uptr) ) ; - } /* end of 'qty_svc' */ + { + return ( qty_common_svc(&qty_dib,uptr) ) ; + } /* end of 'qty_svc' */ - /*--------------------------------------------------------------*/ - /* qty */ - /*--------------------------------------------------------------*/ + /*--------------------------------------------------------------*/ + /* qty */ + /*--------------------------------------------------------------*/ int32 qty( int32 pulse, int32 code, int32 AC ) - { - int32 iodata ; - int32 ioresult ; - int line ; - TMLN * tmlnp ; - int a ; - int kar ; + { + int32 iodata ; + int32 ioresult ; + int line ; + TMLN * tmlnp ; + int a ; + int kar ; - /*--------------------------------------------------------------*/ - /* DG 4060[-compatible] "quad" multiplexor instruction handler */ - /*--------------------------------------------------------------*/ + /*--------------------------------------------------------------*/ + /* DG 4060[-compatible] "quad" multiplexor instruction handler */ + /*--------------------------------------------------------------*/ - ioresult= qty_brkio ; /* (assume returning I/O break value */ - iodata = 0 ; /* (assume 16-bit Nova/Eclipse bus) */ - switch ( code ) - { - case ioNIO : /* */ - break ; + ioresult= qty_brkio ; /* (assume returning I/O break value */ + iodata = 0 ; /* (assume 16-bit Nova/Eclipse bus) */ + switch ( code ) + { + case ioNIO : /* */ + break ; - case ioDIA : /* get current QTY status */ - iodata = qty_update_status( &qty_dib, &qty_desc ) ; - if ( iodata & QTY_S_RI ) - { /* clear line's input buffer */ - QTY_LINE_CLEAR_BIT( (QTY_LINE_EXTRACT(iodata)), (QTY_L_RXBZ | QTY_L_RXDN) ) - /* - character masking ; - parity checking ; - parity generating ; - */ - } - qty_update_status( &qty_dib, &qty_desc ) ; - break ; + case ioDIA : /* get current QTY status */ + iodata = qty_update_status( &qty_dib, &qty_desc ) ; + if ( iodata & QTY_S_RI ) + { /* clear line's input buffer */ + QTY_LINE_CLEAR_BIT( (QTY_LINE_EXTRACT(iodata)), (QTY_L_RXBZ | QTY_L_RXDN) ) + /* + character masking ; + parity checking ; + parity generating ; + */ + } + qty_update_status( &qty_dib, &qty_desc ) ; + break ; - case ioDOA : /* send character to QTY */ - line = QTY_LINE_EXTRACT( iodata ) ; - if ( line < qty_max ) - if ( QTY_LINE_BIT_SET(line,QTY_L_TXE) ) - { - /* - perform any character translation: - 7 bit/ 8 bit - parity generation - */ - kar = AC & ((qty_unit.flags & UNIT_8B)? 0377: 0177) ; - /* do any parity calculations also */ + case ioDOA : /* send character to QTY */ + line = QTY_LINE_EXTRACT( iodata ) ; + if ( line < qty_max ) + if ( QTY_LINE_BIT_SET(line,QTY_L_TXE) ) + { + /* + perform any character translation: + 7 bit/ 8 bit + parity generation + */ + kar = AC & ((qty_unit.flags & UNIT_8B)? 0377: 0177) ; + /* do any parity calculations also */ - tmlnp = &qty_ldsc[ line ] ; - a = qty_tmxr_putc( line, tmlnp, kar ) ; - if ( a != SCPE_OK) - { - /* do anything at this point? */ - } - qty_update_status( &qty_dib, &qty_desc ) ; - } - break ; + tmlnp = &qty_ldsc[ line ] ; + a = qty_tmxr_putc( line, tmlnp, kar ) ; + if ( a != SCPE_OK) + { + /* do anything at this point? */ + } + qty_update_status( &qty_dib, &qty_desc ) ; + } + break ; - case ioDIB : /* no QTY function - return bus noise in AC */ - break ; + case ioDIB : /* no QTY function - return bus noise in AC */ + break ; - case ioDOB : /* clear QTY output channel busy and done flag */ - QTY_LINE_CLEAR_BIT( (QTY_LINE_EXTRACT(AC)), (QTY_L_TXBZ | QTY_L_TXDN) ) - qty_update_status( &qty_dib, &qty_desc ) ; - break ; + case ioDOB : /* clear QTY output channel busy and done flag */ + QTY_LINE_CLEAR_BIT( (QTY_LINE_EXTRACT(AC)), (QTY_L_TXBZ | QTY_L_TXDN) ) + qty_update_status( &qty_dib, &qty_desc ) ; + break ; - case ioDIC : /* no QTY function - return bus noise in AC */ - break ; + case ioDIC : /* no QTY function - return bus noise in AC */ + break ; - case ioDOC : /* no QTY function - ignore */ - break ; + case ioDOC : /* no QTY function - ignore */ + break ; - case ioSKP : /* I/O skip test - should never come here */ - break ; + case ioSKP : /* I/O skip test - should never come here */ + break ; - default : - /* */ - break ; - } + default : + /* */ + break ; + } - switch ( pulse ) - { - case iopN : /* */ - break ; + switch ( pulse ) + { + case iopN : /* */ + break ; - case iopS : /* */ - break ; + case iopS : /* */ + break ; - case iopP : /* */ - break ; + case iopP : /* */ + break ; - case iopC : - qty_update_status( &qty_dib, &qty_desc ) ; - break ; + case iopC : + qty_update_status( &qty_dib, &qty_desc ) ; + break ; - default : - /* */ - break ; - } + default : + /* */ + break ; + } - return ( DG_RETURN( ioresult, iodata ) ) ; - } /* end of 'qty' */ - - /*--------------------------------------------------------------*/ - /* qty_summary */ - /*--------------------------------------------------------------*/ + return ( DG_RETURN( ioresult, iodata ) ) ; + } /* end of 'qty' */ + + /*--------------------------------------------------------------*/ + /* qty_summary */ + /*--------------------------------------------------------------*/ t_stat qty_summary( FILE * st, UNIT * uptr, int32 val, void * desc ) - { - int32 i, t ; + { + int32 i, t ; - for (i = t = 0 ; i < qty_desc.lines ; ++i ) - if ( qty_ldsc[i].conn ) - { - ++t ; - } - fprintf( st, "%d connection%s", t, ((t)? "s" : "") ) ; - return ( SCPE_OK ) ; - } /* end of 'qty_summ' */ + for (i = t = 0 ; i < qty_desc.lines ; ++i ) + if ( qty_ldsc[i].conn ) + { + ++t ; + } + fprintf( st, "%d connection%s", t, ((t)? "s" : "") ) ; + return ( SCPE_OK ) ; + } /* end of 'qty_summ' */ - /*--------------------------------------------------------------*/ - /* qty_show */ - /*--------------------------------------------------------------*/ + /*--------------------------------------------------------------*/ + /* qty_show */ + /*--------------------------------------------------------------*/ t_stat qty_show( FILE * st, UNIT * uptr, int32 val, void * desc ) - { - int32 i, t ; + { + int32 i, t ; - for (i = t = 0 ; i < qty_desc.lines ; ++i ) - if ( qty_ldsc[i].conn ) - { - t = 1; - if ( val ) - { - tmxr_fconns( st, &qty_ldsc[i], i ) ; - } - else - { - tmxr_fstats( st, &qty_ldsc[i], i ) ; - } - } - if ( t == 0 ) fprintf( st, "none connected\n" ) ; - return ( SCPE_OK ) ; - } /* end of 'qty_show' */ + for (i = t = 0 ; i < qty_desc.lines ; ++i ) + if ( qty_ldsc[i].conn ) + { + t = 1; + if ( val ) + { + tmxr_fconns( st, &qty_ldsc[i], i ) ; + } + else + { + tmxr_fstats( st, &qty_ldsc[i], i ) ; + } + } + if ( t == 0 ) fprintf( st, "none connected\n" ) ; + return ( SCPE_OK ) ; + } /* end of 'qty_show' */ - /*--------------------------------------------------------------*/ - /* qty_setnl */ - /*--------------------------------------------------------------*/ + /*--------------------------------------------------------------*/ + /* qty_setnl */ + /*--------------------------------------------------------------*/ t_stat qty_setnl( UNIT * uptr, int32 val, char * cptr, void * desc ) - { - int32 newln, i, t ; + { + int32 newln, i, t ; - t_stat r ; - if ( cptr == NULL ) - { - return ( SCPE_ARG ) ; - } - newln = (int32) get_uint( cptr, 10, QTY_MAX, &r ) ; - if ( (r != SCPE_OK) || (newln == qty_desc.lines) ) - { - return ( r ) ; - } - if ( (newln == 0) || (newln > QTY_MAX) ) - { - return ( SCPE_ARG ) ; - } - if ( newln < qty_desc.lines ) - { - for ( i = newln, t = 0 ; i < qty_desc.lines ; ++i ) - { - t = t | qty_ldsc[i].conn ; - } - if ( t && ! get_yn("This will disconnect users; proceed [N]?", FALSE) ) - { - return ( SCPE_OK ) ; - } - for ( i = newln ; i < qty_desc.lines ; ++i ) - { - if ( qty_ldsc[i].conn ) - { /* reset line */ - tmxr_msg( qty_ldsc[i].conn, "\r\nOperator disconnected line\r\n" ) ; - tmxr_reset_ln( &qty_ldsc[i] ) ; - } - qty_clear( TRUE ) ; /* reset mux */ - } - } - qty_max = qty_desc.lines = newln ; - /* Huh, I don't understand this yet... - qty_max = ((qty_dev.flags & DEV_DIS)? 0 : (qty_desc.lines / QTY_MAX)) ; - */ - return ( SCPE_OK ) ; - } /* end of 'qty_setnl' */ + t_stat r ; + if ( cptr == NULL ) + { + return ( SCPE_ARG ) ; + } + newln = (int32) get_uint( cptr, 10, QTY_MAX, &r ) ; + if ( (r != SCPE_OK) || (newln == qty_desc.lines) ) + { + return ( r ) ; + } + if ( (newln == 0) || (newln > QTY_MAX) ) + { + return ( SCPE_ARG ) ; + } + if ( newln < qty_desc.lines ) + { + for ( i = newln, t = 0 ; i < qty_desc.lines ; ++i ) + { + t = t | qty_ldsc[i].conn ; + } + if ( t && ! get_yn("This will disconnect users; proceed [N]?", FALSE) ) + { + return ( SCPE_OK ) ; + } + for ( i = newln ; i < qty_desc.lines ; ++i ) + { + if ( qty_ldsc[i].conn ) + { /* reset line */ + tmxr_msg( qty_ldsc[i].conn, "\r\nOperator disconnected line\r\n" ) ; + tmxr_reset_ln( &qty_ldsc[i] ) ; + } + qty_clear( TRUE ) ; /* reset mux */ + } + } + qty_max = qty_desc.lines = newln ; + /* Huh, I don't understand this yet... + qty_max = ((qty_dev.flags & DEV_DIS)? 0 : (qty_desc.lines / QTY_MAX)) ; + */ + return ( SCPE_OK ) ; + } /* end of 'qty_setnl' */ /*----------------------------------------------------------------------*/ -/* ALM [425x-compatible] multiplexor */ +/* ALM [425x-compatible] multiplexor */ /*----------------------------------------------------------------------*/ /* - * device code: 034 [primary], - * 074 [secondary] - * interrupt mask: B14 [000002] - * ASM mnemonic: ALM + * device code: 034 [primary], + * 074 [secondary] + * interrupt mask: B14 [000002] + * ASM mnemonic: ALM * - * ALM [4255-4258] I/O instructions + * ALM [4255-4258] I/O instructions * - * DIA read line and section requesting service - * DOA select line and section (lines 0-255, 8-bits) + rcvr/xmit - * DIB receive data - * DOB 00 transmit data - * 01 transmit BREAK - * 10 set modem control status - * 11 - * DIC read receiver or modem status - * DOC 00 control line section and diag mode - * 01 - * 10 specify line characteristics - * 11 + * DIA read line and section requesting service + * DOA select line and section (lines 0-255, 8-bits) + rcvr/xmit + * DIB receive data + * DOB 00 transmit data + * 01 transmit BREAK + * 10 set modem control status + * 11 + * DIC read receiver or modem status + * DOC 00 control line section and diag mode + * 01 + * 10 specify line characteristics + * 11 * - * undocumented DG "features": + * undocumented DG "features": * - * NIOS sets board offline - * NIOC sets board online - * Modem control signal state change can signal interrupt - * explicit line select with DOA - * implicit line select with DIA + * NIOS sets board offline + * NIOC sets board online + * Modem control signal state change can signal interrupt + * explicit line select with DOA + * implicit line select with DIA * - * We support 64 lines maximum in this release although some ALM's could - * theoretically support up to 256. + * We support 64 lines maximum in this release although some ALM's could + * theoretically support up to 256. */ -DIB alm_dib = { DEV_ALM, INT_ALM, PI_ALM, &alm } ; -UNIT alm_unit = - { - UDATA (&alm_svc, (UNIT_ATTABLE), 0) - } ; +DIB alm_dib = { DEV_ALM, INT_ALM, PI_ALM, &alm } ; +UNIT alm_unit = + { + UDATA (&alm_svc, (UNIT_ATTABLE), 0) + } ; -REG alm_reg[] = /* ('qty_reg' should be similar to this except for device code related items) */ - { - { ORDATA (BUF, alm_unit.buf, 8) }, - { FLDATA (BUSY, dev_busy, INT_V_ALM) }, - { FLDATA (DONE, dev_done, INT_V_ALM) }, - { FLDATA (DISABLE, dev_disable, INT_V_ALM) }, - { FLDATA (INT, int_req, INT_V_ALM) }, +REG alm_reg[] = /* ('qty_reg' should be similar to this except for device code related items) */ + { + { ORDATA (BUF, alm_unit.buf, 8) }, + { FLDATA (BUSY, dev_busy, INT_V_ALM) }, + { FLDATA (DONE, dev_done, INT_V_ALM) }, + { FLDATA (DISABLE, dev_disable, INT_V_ALM) }, + { FLDATA (INT, int_req, INT_V_ALM) }, - { FLDATA (MDMCTL, qty_mdm, 0) }, - { FLDATA (AUTODS, qty_auto, 0) }, - { DRDATA (POLLS, qty_polls, 32) }, - { NULL } - } ; + { FLDATA (MDMCTL, qty_mdm, 0) }, + { FLDATA (AUTODS, qty_auto, 0) }, + { DRDATA (POLLS, qty_polls, 32) }, + { NULL } + } ; -DEVICE alm_dev = - { - "ALM", &alm_unit, alm_reg, qty_mod, - 1, 10, 31, 1, 8, 8, - NULL, NULL, &alm_reset, - NULL, &qty_attach, &qty_detach, - &alm_dib, (DEV_DISABLE | DEV_NET) - } ; +DEVICE alm_dev = + { + "ALM", &alm_unit, alm_reg, qty_mod, + 1, 10, 31, 1, 8, 8, + NULL, NULL, &alm_reset, + NULL, &qty_attach, &qty_detach, + &alm_dib, (DEV_DISABLE | DEV_NET) + } ; -int alm_section = -1 ; /* current line "section" (0 = RCV, 1 = XMT) */ -int alm_line = -1 ; /* current line [0-63] */ -int alm_diag_mode = 0 ; /* */ -int alm_line_mask = 0x003F ; /* maximum of 64 lines in this rev */ +int alm_section = -1 ; /* current line "section" (0 = RCV, 1 = XMT) */ +int alm_line = -1 ; /* current line [0-63] */ +int alm_diag_mode = 0 ; /* */ +int alm_line_mask = 0x003F ; /* maximum of 64 lines in this rev */ -#define ALM_LINE_EXTRACT( x ) (((x) >> 1) & alm_line_mask) -#define ALM_SECT_EXTRACT( x ) ((x) & 0x0001) +#define ALM_LINE_EXTRACT( x ) (((x) >> 1) & alm_line_mask) +#define ALM_SECT_EXTRACT( x ) ((x) & 0x0001) - /*--------------------------------------------------------------*/ - /* alm_reset */ - /*--------------------------------------------------------------*/ + /*--------------------------------------------------------------*/ + /* alm_reset */ + /*--------------------------------------------------------------*/ t_stat alm_reset( DEVICE * dptr ) - { - return ( qty_common_reset(&alm_dib,&alm_unit,dptr) ) ; - } /* end of 'alm_reset' */ + { + return ( qty_common_reset(&alm_dib,&alm_unit,dptr) ) ; + } /* end of 'alm_reset' */ - /*--------------------------------------------------------------*/ - /* alm_svc */ - /*--------------------------------------------------------------*/ + /*--------------------------------------------------------------*/ + /* alm_svc */ + /*--------------------------------------------------------------*/ t_stat alm_svc( UNIT * uptr ) - { - return ( qty_common_svc(&alm_dib,uptr) ) ; - } /* end of 'alm_svc' */ + { + return ( qty_common_svc(&alm_dib,uptr) ) ; + } /* end of 'alm_svc' */ - /*--------------------------------------------------------------*/ - /* alm */ - /*--------------------------------------------------------------*/ + /*--------------------------------------------------------------*/ + /* alm */ + /*--------------------------------------------------------------*/ int32 alm( int32 pulse, int32 code, int32 AC ) - { - int32 iodata ; - int32 ioresult ; - TMLN * tmlnp ; - int a ; - int kar ; + { + int32 iodata ; + int32 ioresult ; + TMLN * tmlnp ; + int a ; + int kar ; - /*--------------------------------------------------------------*/ - /* DG 425x[-compatible] "ALM" multiplexor instruction handler */ - /*--------------------------------------------------------------*/ + /*--------------------------------------------------------------*/ + /* DG 425x[-compatible] "ALM" multiplexor instruction handler */ + /*--------------------------------------------------------------*/ - ioresult= qty_brkio ; /* (assume returning I/O break value */ - iodata = 0 ; /* (assume 16-bit Nova/Eclipse bus) */ - switch ( code ) - { - case ioNIO : /* */ - break ; + ioresult= qty_brkio ; /* (assume returning I/O break value */ + iodata = 0 ; /* (assume 16-bit Nova/Eclipse bus) */ + switch ( code ) + { + case ioNIO : /* */ + break ; - case ioDIA : /* read line and section requesting service */ - iodata = qty_update_status( &alm_dib, &qty_desc ) ; - alm_line = (QTY_LINE_EXTRACT(iodata) & alm_line_mask) ; - /* (mask with 'alm_line_mask' in case ALM mask is different than QTY */ - alm_section = 0 ; - if ( ! ( iodata & QTY_S_RI) ) - if ( iodata & QTY_S_TI ) - { - alm_section = 1 ; /* receiver quiet - transmitter done */ - } - iodata = (alm_line << 1) | alm_section ; - break ; + case ioDIA : /* read line and section requesting service */ + iodata = qty_update_status( &alm_dib, &qty_desc ) ; + alm_line = (QTY_LINE_EXTRACT(iodata) & alm_line_mask) ; + /* (mask with 'alm_line_mask' in case ALM mask is different than QTY */ + alm_section = 0 ; + if ( ! ( iodata & QTY_S_RI) ) + if ( iodata & QTY_S_TI ) + { + alm_section = 1 ; /* receiver quiet - transmitter done */ + } + iodata = (alm_line << 1) | alm_section ; + break ; - case ioDOA : /* set line and section */ - alm_section = ALM_SECT_EXTRACT( AC ) ; - alm_line = ALM_LINE_EXTRACT( AC ) ; - break ; + case ioDOA : /* set line and section */ + alm_section = ALM_SECT_EXTRACT( AC ) ; + alm_line = ALM_LINE_EXTRACT( AC ) ; + break ; - case ioDIB : /* no ALM function - return bus noise in AC */ - if ( alm_line < qty_max ) - { - iodata = QTY_LINE_RX_CHAR( alm_line ) ; - } - break ; + case ioDIB : /* no ALM function - return bus noise in AC */ + if ( alm_line < qty_max ) + { + iodata = QTY_LINE_RX_CHAR( alm_line ) ; + } + break ; - case ioDOB : /* output and modem control functions */ - switch ( (AC >> 14) & 03 ) - { - case 00 : /* transmit data */ - if ( alm_line < qty_max ) - if ( QTY_LINE_BIT_SET(alm_line,QTY_L_TXE) ) - { - /* - perform any character translation: - 7 bit/ 8 bit - parity generation - */ - kar = AC & ((alm_unit.flags & UNIT_8B)? 0377: 0177) ; - /* do any parity calculations also */ + case ioDOB : /* output and modem control functions */ + switch ( (AC >> 14) & 03 ) + { + case 00 : /* transmit data */ + if ( alm_line < qty_max ) + if ( QTY_LINE_BIT_SET(alm_line,QTY_L_TXE) ) + { + /* + perform any character translation: + 7 bit/ 8 bit + parity generation + */ + kar = AC & ((alm_unit.flags & UNIT_8B)? 0377: 0177) ; + /* do any parity calculations also */ - tmlnp = &qty_ldsc[ alm_line ] ; - a = qty_tmxr_putc( alm_line, tmlnp, kar ) ; - if ( a != SCPE_OK) - { - /* do anything at this point? */ - } - qty_update_status( &alm_dib, &qty_desc ) ; - } - break ; + tmlnp = &qty_ldsc[ alm_line ] ; + a = qty_tmxr_putc( alm_line, tmlnp, kar ) ; + if ( a != SCPE_OK) + { + /* do anything at this point? */ + } + qty_update_status( &alm_dib, &qty_desc ) ; + } + break ; - case 01 : /* transmit break */ - if ( alm_line < qty_max ) - if ( QTY_LINE_BIT_SET(alm_line,QTY_L_TXE) ) - { - tmlnp = &qty_ldsc[ alm_line ] ; - /* - a = qty_tmxr_putc( alm_line, tmlnp, kar ) ; - if ( a != SCPE_OK) - { - } - */ - qty_update_status( &alm_dib, &qty_desc ) ; - } - break ; + case 01 : /* transmit break */ + if ( alm_line < qty_max ) + if ( QTY_LINE_BIT_SET(alm_line,QTY_L_TXE) ) + { + tmlnp = &qty_ldsc[ alm_line ] ; + /* + a = qty_tmxr_putc( alm_line, tmlnp, kar ) ; + if ( a != SCPE_OK) + { + } + */ + qty_update_status( &alm_dib, &qty_desc ) ; + } + break ; - case 02 : /* set modem control status */ - break ; + case 02 : /* set modem control status */ + break ; - case 03 : /* unused */ - break ; - } - break ; + case 03 : /* unused */ + break ; + } + break ; - case ioDIC : /* get modem or receiver status */ - if ( alm_line < qty_max ) - if ( alm_section ) - { - /* get modem section status */ - if ( qty_ldsc[ alm_line ].xmte ) - { - iodata = 0035 ; /* set CD, CTS, DSR, MDM flags */ - } - } - else - { - /* get receiver section status */ - iodata = 0 ; /* receiver error status - no errors by default */ - } - break ; + case ioDIC : /* get modem or receiver status */ + if ( alm_line < qty_max ) + if ( alm_section ) + { + /* get modem section status */ + if ( qty_ldsc[ alm_line ].xmte ) + { + iodata = 0035 ; /* set CD, CTS, DSR, MDM flags */ + } + } + else + { + /* get receiver section status */ + iodata = 0 ; /* receiver error status - no errors by default */ + } + break ; - case ioDOC : /* set line attributes */ - switch ( (AC >> 14) & 03 ) - { - case 00 : /* control line section */ - break ; + case ioDOC : /* set line attributes */ + switch ( (AC >> 14) & 03 ) + { + case 00 : /* control line section */ + break ; - case 01 : /* unused */ - break ; + case 01 : /* unused */ + break ; - case 02 : /* set line characteristics */ - break ; + case 02 : /* set line characteristics */ + break ; - case 03 : /* unused */ - break ; - } - break ; + case 03 : /* unused */ + break ; + } + break ; - case ioSKP : /* I/O skip test - should never come here */ - break ; + case ioSKP : /* I/O skip test - should never come here */ + break ; - default : - /* */ - break ; - } + default : + /* */ + break ; + } - switch ( pulse ) - { - case iopN : /* */ - break ; + switch ( pulse ) + { + case iopN : /* */ + break ; - case iopS : /* set device busy - * set all lines on board offline - * clear each line's done - * clear internal system - * clear device busy - */ - for ( a = 0 ; a < qty_max ; ++a ) - if ( 1 ) - { - QTY_LINE_CLEAR_BIT( a, (QTY_L_RXBZ | QTY_L_RXDN | QTY_L_TXBZ | QTY_L_TXDN) ) ; - } - qty_update_status( &alm_dib, &qty_desc ) ; - break ; + case iopS : /* set device busy + * set all lines on board offline + * clear each line's done + * clear internal system + * clear device busy + */ + for ( a = 0 ; a < qty_max ; ++a ) + if ( 1 ) + { + QTY_LINE_CLEAR_BIT( a, (QTY_L_RXBZ | QTY_L_RXDN | QTY_L_TXBZ | QTY_L_TXDN) ) ; + } + qty_update_status( &alm_dib, &qty_desc ) ; + break ; - case iopP : /* stop clock for all boards in off-line mode */ - break ; + case iopP : /* stop clock for all boards in off-line mode */ + break ; - case iopC : - for ( a = 0 ; a < qty_max ; ++a ) - if ( 1 ) - { - QTY_LINE_CLEAR_BIT( a, (QTY_L_RXBZ | QTY_L_RXDN | QTY_L_TXBZ | QTY_L_TXDN) ) ; - } - qty_update_status( &alm_dib, &qty_desc ) ; - break ; + case iopC : + for ( a = 0 ; a < qty_max ; ++a ) + if ( 1 ) + { + QTY_LINE_CLEAR_BIT( a, (QTY_L_RXBZ | QTY_L_RXDN | QTY_L_TXBZ | QTY_L_TXDN) ) ; + } + qty_update_status( &alm_dib, &qty_desc ) ; + break ; - default : - /* */ - break ; - } + default : + /* */ + break ; + } - return ( DG_RETURN( ioresult, iodata ) ) ; - } /* end of 'alm' */ + return ( DG_RETURN( ioresult, iodata ) ) ; + } /* end of 'alm' */ diff --git a/NOVA/nova_sys.c b/NOVA/nova_sys.c index 9adc3cfe..c5a278a6 100644 --- a/NOVA/nova_sys.c +++ b/NOVA/nova_sys.c @@ -1,6 +1,6 @@ /* nova_sys.c: NOVA simulator interface - Copyright (c) 1993-2004, Robert M. Supnik + Copyright (c) 1993-2005, 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"), @@ -19,25 +19,25 @@ 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 + 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. - 26-Mar-04 RMS Fixed warning with -std=c99 - 14-Jan-04 BKR Added support for QTY and ALM - 04-Jan-04 RMS Fixed 64b issues found by VMS 8.1 - 24-Nov-03 CEO Added symbolic support for LEF instruction - 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) + 26-Mar-04 RMS Fixed warning with -std=c99 + 14-Jan-04 BKR Added support for QTY and ALM + 04-Jan-04 RMS Fixed 64b issues found by VMS 8.1 + 24-Nov-03 CEO Added symbolic support for LEF instruction + 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" @@ -72,12 +72,12 @@ 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 + 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) @@ -91,55 +91,57 @@ REG *sim_PC = &cpu_reg[0]; int32 sim_emax = 4; DEVICE *sim_devices[] = { - &cpu_dev, + &cpu_dev, #if defined (ECLIPSE) - &map_dev, - &fpu_dev, - &pit_dev, + &map_dev, + &fpu_dev, + &pit_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, - &qty_dev, - &alm_dev, - NULL }; + &ptr_dev, + &ptp_dev, + &tti_dev, + &tto_dev, + &tti1_dev, + &tto1_dev, + &clk_dev, + &plt_dev, + &lpt_dev, + &dsk_dev, + &dkp_dev, + &mta_dev, + &qty_dev, + &alm_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" }; - + "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 --- + 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. @@ -155,118 +157,125 @@ 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 */ + 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) +#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 }; + 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", @@ -392,7 +401,8 @@ static const char *opcode[] = { #if defined (ECLIPSE) "LEF", "LEF", "LEF", "LEF", #endif - NULL }; + NULL + }; static const int32 opc_val[] = { 0000000+I_M, 0004000+I_M, 0010000+I_M, 0014000+I_M, @@ -518,11 +528,13 @@ static const int32 opc_val[] = { #if defined (ECLIPSE) 0064000+I_D, 0070000+I_D, 0074000+I_D, 0076000+I_D, #endif - -1 }; + -1 + }; static const char *skip[] = { "SKP", "SZC", "SNC", "SZR", "SNR", "SEZ", "SBN", - NULL }; + NULL + }; static const char *device[] = { #if defined (ECLIPSE) @@ -531,7 +543,8 @@ static const char *device[] = { "TTI", "TTO", "PTR", "PTP", "RTC", "PLT", "CDR", "LPT", "DSK", "MTA", "DCM", "ADCV", "DKP", "CAS", "TTI1", "TTO1", "CPU", - NULL }; + NULL + }; static const int32 dev_val[] = { #if defined (ECLIPSE) @@ -540,68 +553,77 @@ static const int32 dev_val[] = { 010, 011, 012, 013, 014, 015, 016, 017, 020, 022, 024, 030, 033, 034, 050, 051, 077, - -1 }; - + -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 + *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 + return = error code */ t_stat fprint_addr (FILE *of, t_addr addr, int32 ind, int32 mode, - int32 disp, t_bool ext, int32 cflag) + int32 disp, t_bool ext, int32 cflag) { int32 dsign, dmax; -if (ext) dmax = AMASK + 1; /* get max disp */ +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 */ +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 + *of = output stream + addr = current PC + *val = pointer to values + *uptr = pointer to unit + sw = switches Outputs: - status = error code + status = error code */ t_stat fprint_sym (FILE *of, t_addr addr, t_value *val, - UNIT *uptr, int32 sw) + UNIT *uptr, int32 sw) { int32 cflag, i, j, c1, c2, inst, inst1, dv, src, dst, skp; int32 ind, mode, disp, dev; @@ -610,132 +632,154 @@ int32 byac, extind, extdisp, xop; cflag = (uptr == NULL) || (uptr == &cpu_unit); c1 = ((int32) val[0] >> 8) & 0177; c2 = (int32) 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? */ - +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 = (int32) val[0]; inst1 = (int32) val[1]; -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 = inst1 & A_IND; /* extended fields */ - extdisp = inst1 & AMASK; - for (dv = 0; (dev_val[dv] >= 0) && (dev_val[dv] != dev); dv++) ; +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 = inst1 & A_IND; /* extended fields */ + extdisp = inst1 & 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 */ + 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 defined (ECLIPSE) - if (Usermap && (MapStat & 0100)) { /* the evil LEF mode */ - fprintf (of, "LEF %-o,", dst); - fprint_addr (of, addr, ind, mode, disp, FALSE, cflag); - break; - } + if (Usermap && (MapStat & 0100)) { /* the evil LEF mode */ + fprintf (of, "LEF %-o,", dst); + fprint_addr (of, addr, ind, mode, disp, FALSE, cflag); + break; + } #endif - 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], inst1); - return -1; - case I_V_RLI: /* reg, long imm */ - fprintf (of, "%s %-o,%-o", opcode[i], inst1, 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 */ - default: - fprintf (of, "??? [%-o]", inst); - break; } - return SCPE_OK; } /* end if */ - } /* end for */ + 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], inst1); + return -1; + + case I_V_RLI: /* reg, long imm */ + fprintf (of, "%s %-o,%-o", opcode[i], inst1, 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 */ + + default: + fprintf (of, "??? [%-o]", inst); + break; + } + 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 + *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 + 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 */ +#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) { @@ -743,81 +787,92 @@ int32 d, r, x, pflag; char gbuf[CBUFSIZE]; int32 dmax, dsign; -if (ext) dmax = AMASK + 1; /* get max disp */ +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 */ +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 = (int32) 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 = (int32) get_uint (gbuf, 8, I_M_DST, &r); - if ((r != SCPE_OK) || (x < 2)) return NULL; - pflag = pflag | A_NX; } - -/* Address parse, continued */ +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 = (int32) 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 = (int32) get_uint (gbuf, 8, I_M_DST, &r); + if ((r != SCPE_OK) || (x < 2)) return NULL; + pflag = pflag | A_NX; + } + +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 */ -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 + *cptr = input string + term = second terminating character + val = output array Outputs: - optr = pointer to next char in input string - NULL if error + optr = pointer to next char in input string + NULL if error */ char *get_2reg (char *cptr, char term, int32 *val) @@ -825,25 +880,25 @@ char *get_2reg (char *cptr, char term, int32 *val) char gbuf[CBUFSIZE]; t_stat r; -cptr = get_glyph (cptr, gbuf, ','); /* get register */ +cptr = get_glyph (cptr, gbuf, ','); /* get register */ val[0] = (int32) get_uint (gbuf, 8, I_M_SRC, &r); if (r != SCPE_OK) return NULL; -cptr = get_glyph (cptr, gbuf, term); /* get register */ +cptr = get_glyph (cptr, gbuf, term); /* get register */ val[1] = (int32) 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 + *cptr = pointer to input string + addr = current PC + *uptr = pointer to unit + *val = pointer to output values + sw = switches Outputs: - status = error status + status = error status */ t_stat parse_sym (char *cptr, t_addr addr, UNIT *uptr, t_value *val, int32 sw) @@ -853,145 +908,165 @@ t_stat r, rtn; char gbuf[CBUFSIZE]; cflag = (uptr == NULL) || (uptr == &cpu_unit); -while (isspace (*cptr)) cptr++; /* absorb spaces */ +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 (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; } - + 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 */ +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 */ +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 = (int32) 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 = (int32) 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 = (int32) 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 = (int32) 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 = (int32) 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 = (int32) 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] = (int32) get_uint (gbuf, 8, DMASK, &r); - if (r != SCPE_OK) return SCPE_ARG; - cptr = get_glyph (cptr, gbuf, 0); /* get register */ - d = (int32) 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] = (int32) 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 = (int32) 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 = (int32) 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 = (int32) 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? */ +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 = (int32) 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 = (int32) 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 = (int32) 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 = (int32) 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 if */ + 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 = (int32) 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 = (int32) 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] = (int32) get_uint (gbuf, 8, DMASK, &r); + if (r != SCPE_OK) return SCPE_ARG; + cptr = get_glyph (cptr, gbuf, 0); /* get register */ + d = (int32) 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] = (int32) 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 = (int32) 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 = (int32) 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 = (int32) 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 index dd1368a7..a15ee97b 100644 --- a/NOVA/nova_tt.c +++ b/NOVA/nova_tt.c @@ -1,6 +1,6 @@ /* nova_tt.c: NOVA console terminal simulator - Copyright (c) 1993-2004, Robert M. Supnik + Copyright (c) 1993-2005, 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"), @@ -19,28 +19,28 @@ 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 + 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 + tti terminal input + tto terminal output - 29-Dec-03 RMS Added console backpressure support - 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 + 29-Dec-03 RMS Added console backpressure support + 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) +#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); @@ -50,13 +50,13 @@ 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 + 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 }; @@ -64,32 +64,35 @@ 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 } }; + { 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 } }; + { 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 }; + "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 + 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 }; @@ -97,22 +100,24 @@ 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 } }; + { 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 }; - + "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) @@ -120,17 +125,21 @@ 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 */ +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; } @@ -140,13 +149,13 @@ 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? */ +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 */ + 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; @@ -157,31 +166,35 @@ return SCPE_OK; 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 */ +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 */ +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 */ +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; } @@ -194,11 +207,12 @@ t_stat r; c = tto_unit.buf & 0177; if ((tto_unit.flags & UNIT_DASHER) && (c == 031)) c = '\b'; -if ((r = sim_putchar_s (c)) != SCPE_OK) { /* output; error? */ - sim_activate (uptr, uptr->wait); /* try again */ - return ((r == SCPE_STALL)? SCPE_OK: r); } /* !stall? report */ -dev_busy = dev_busy & ~INT_TTO; /* clear busy */ -dev_done = dev_done | INT_TTO; /* set done */ +if ((r = sim_putchar_s (c)) != SCPE_OK) { /* output; error? */ + sim_activate (uptr, uptr->wait); /* try again */ + return ((r == SCPE_STALL)? SCPE_OK: r); /* !stall? report */ + } +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); tto_unit.pos = tto_unit.pos + 1; return SCPE_OK; @@ -209,10 +223,10 @@ return SCPE_OK; 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 */ +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 */ +sim_cancel (&tto_unit); /* deactivate unit */ return SCPE_OK; } diff --git a/NOVA/nova_tt1.c b/NOVA/nova_tt1.c index 5b31f137..6e014f8d 100644 --- a/NOVA/nova_tt1.c +++ b/NOVA/nova_tt1.c @@ -20,38 +20,38 @@ 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 + 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 + 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 + 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) +#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 */ +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); @@ -66,13 +66,13 @@ 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 + 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 }; @@ -80,39 +80,42 @@ 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 } }; + { 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 } }; + { 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 }; + "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 + 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 }; @@ -120,27 +123,30 @@ 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 } }; + { 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 } }; + { 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 }; - + "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) @@ -148,17 +154,21 @@ 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 */ +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; } @@ -168,23 +178,27 @@ 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 */ +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; } @@ -192,38 +206,43 @@ return SCPE_OK; t_stat tti1_reset (DEVICE *dptr) { -ttx1_enbdis (dptr->flags & DEV_DIS); /* sync devices */ +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 */ +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 */ +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 */ +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; } @@ -233,18 +252,21 @@ t_stat tto1_svc (UNIT *uptr) { int32 c; -dev_busy = dev_busy & ~INT_TTO1; /* clear busy */ -dev_done = dev_done | INT_TTO1; /* set done */ +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; } } +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; } @@ -252,12 +274,12 @@ return SCPE_OK; t_stat tto1_reset (DEVICE *dptr) { -ttx1_enbdis (dptr->flags & DEV_DIS); /* sync devices */ +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 */ +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 */ +sim_cancel (&tto1_unit); /* deactivate unit */ return SCPE_OK; } @@ -274,9 +296,9 @@ 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 */ +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; } @@ -286,9 +308,9 @@ 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 */ +r = tmxr_detach (&tt_desc, uptr); /* detach */ +tt1_ldsc.rcve = 0; /* disable rcv */ +sim_cancel (uptr); /* stop poll */ return r; } @@ -315,9 +337,12 @@ return SCPE_OK; 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; } + 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 index 028532f5..29af7841 100644 --- a/PDP1/pdp1_cpu.c +++ b/PDP1/pdp1_cpu.c @@ -1,6 +1,6 @@ /* pdp1_cpu.c: PDP-1 CPU simulator - Copyright (c) 1993-2004, Robert M. Supnik + Copyright (c) 1993-2005, 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"), @@ -19,24 +19,25 @@ 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 + 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 + cpu PDP-1 central processor - 09-Nov-04 RMS Added instruction history - 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 + 16-Aug-05 RMS Fixed C++ declaration and cast problems + 09-Nov-04 RMS Added instruction history + 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 @@ -45,29 +46,28 @@ 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) + 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, + 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: @@ -76,35 +76,35 @@ | op |in| address | memory reference +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - <0:4> <5> mnemonic action + <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 + 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 + 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 + 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 @@ -112,24 +112,23 @@ 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: + + 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 + | | | | | | \______/ \______/ + | | | | | | | | + | | | | | | | +---- program flags + | | | | | | +------------- sense switches + | | | | | +------------------- AC == 0 + | | | | +---------------------- AC >= 0 + | | | +------------------------- AC < 0 + | | +---------------------------- OV == 0 + | +------------------------------- IO >= 0 + +------------------------------------- invert skip The shift format is: @@ -145,13 +144,12 @@ | 1 1 1 0 0| S| immediate | LAW +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - <0:4> mnemonic action + <0:4> mnemonic action - 70 LAW if S = 0, AC = IR<6:17> - else AC = ~IR<6:17> -*/ - -/* The I/O transfer format is: + 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 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ @@ -170,21 +168,20 @@ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | 1 1 1 1 1| | | | | | | | | | | | | | operate +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - | | | | | | | \______/ - | | | | | | | | - | | | | | | | +---- PF select - | | | | | | +---------- clear/set PF - | | | | | +------------------- or PC - | | | | +---------------------- clear AC - | | | +------------------------- halt - | | +---------------------------- CMA - | +------------------------------- or TW - +---------------------------------- clear IO + | | | | | | | \______/ + | | | | | | | | + | | | | | | | +---- 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. + + 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. @@ -193,13 +190,13 @@ 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 + 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). @@ -215,63 +212,65 @@ 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 + 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) +#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) -#define HIST_PC 0x40000000 -#define HIST_V_SHF 18 -#define HIST_MIN 64 -#define HIST_MAX 65536 -struct InstHistory { - uint32 pc; - uint32 ir; - uint32 ovac; - uint32 pfio; - uint32 ea; - uint32 opnd; }; +#define HIST_PC 0x40000000 +#define HIST_V_SHF 18 +#define HIST_MIN 64 +#define HIST_MAX 65536 -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 */ -int32 hst_p = 0; /* history pointer */ -int32 hst_lnt = 0; /* history length */ -struct InstHistory *hst = NULL; /* instruction history */ +typedef struct { + uint32 pc; + uint32 ir; + uint32 ovac; + uint32 pfio; + uint32 ea; + uint32 opnd; + } InstHistory; + +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 */ +int32 hst_p = 0; /* history pointer */ +int32 hst_lnt = 0; /* history length */ +InstHistory *hst = NULL; /* instruction history */ extern UNIT *sim_clock_queue; extern int32 sim_int_char; -extern int32 sim_brk_types, sim_brk_dflt, sim_brk_summ; /* breakpoint info */ +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); @@ -287,103 +286,106 @@ 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 */ -}; - + 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 + 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) }, - { ORDATA (CPLS, cpls, 6) }, - { 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 } }; + { 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) }, + { ORDATA (CPLS, cpls, 6) }, + { 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 }, - { MTAB_XTD|MTAB_VDV|MTAB_NMO|MTAB_SHP, 0, "HISTORY", "HISTORY", - &cpu_set_hist, &cpu_show_hist }, - { 0 } }; + { 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 }, + { MTAB_XTD|MTAB_VDV|MTAB_NMO|MTAB_SHP, 0, "HISTORY", "HISTORY", + &cpu_set_hist, &cpu_show_hist }, + { 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 }; - + "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; @@ -392,357 +394,389 @@ 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 }; + 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)) +#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 */ +while (reason == 0) { /* loop until halted */ -if (sim_interval <= 0) { /* check clock queue */ - if (reason = sim_process_event ()) break; } + 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 (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; + } -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; -if (hst_lnt) { /* history enabled? */ - hst_p = (hst_p + 1); /* next entry */ - if (hst_p >= hst_lnt) hst_p = 0; - hst[hst_p].pc = MA | HIST_PC; /* save PC, IR, LAC, MQ */ - hst[hst_p].ir = IR; - hst[hst_p].ovac = (OV << HIST_V_SHF) | AC; - hst[hst_p].pfio = (PF << HIST_V_SHF) | IO; } + 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; + if (hst_lnt) { /* history enabled? */ + hst_p = (hst_p + 1); /* next entry */ + if (hst_p >= hst_lnt) hst_p = 0; + hst[hst_p].pc = MA | HIST_PC; /* save PC, IR, LAC, MQ */ + hst[hst_p].ir = IR; + hst[hst_p].ovac = (OV << HIST_V_SHF) | AC; + hst[hst_p].pfio = (PF << HIST_V_SHF) | IO; + } -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; } + 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; } /* end if loop */ - } /* end else !extm */ - } /* end if indirect */ - if (hst_p) { /* history enabled? */ - hst[hst_p].ea = MA; - hst[hst_p].opnd = M[MA]; } - } + 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; + } + } /* end else !extm */ + } /* end if indirect */ + if (hst_p) { /* history enabled? */ + hst[hst_p].ea = MA; + hst[hst_p].opnd = M[MA]; + } + } + + switch (op) { /* decode IR<0:4> */ -switch (op) { /* decode IR<0:4> */ - /* Logical, load, store instructions */ -case 001: /* AND */ - AC = AC & M[MA]; - break; + case 001: /* AND */ + AC = AC & M[MA]; + break; -case 002: /* IOR */ - AC = AC | M[MA]; - break; + case 002: /* IOR */ + AC = AC | M[MA]; + break; -case 003: /* XOR */ - 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 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 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 010: /* LAC */ + AC = M[MA]; + break; -case 011: /* LIO */ - IO = M[MA]; - break; + case 011: /* LIO */ + IO = M[MA]; + break; -case 012: /* DAC */ - if (MEM_ADDR_OK (MA)) M[MA] = AC; - 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 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 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 015: /* DIO */ + if (MEM_ADDR_OK (MA)) M[MA] = IO; + break; + + case 016: /* DZM */ + if (MEM_ADDR_OK (MA)) M[MA] = 0; + 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 + 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 + 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 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 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 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 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 024: /* SAD */ + if (AC != M[MA]) PC = INCR_ADDR (PC); + break; -case 025: /* SAS */ - 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 030: /* JMP */ + PCQ_ENTRY; + PC = MA; + break; -case 031: /* JSP */ - AC = EPC_WORD; - 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; -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 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; -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 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; -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; - + 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, @@ -753,88 +787,109 @@ case 033: 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. + > 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; + 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 */ -default: /* undefined */ - reason = STOP_RSRV; /* halt */ - break; } /* end switch opcode */ -} /* end while */ -pcq_r->qptr = pcq_p; /* update pc q ptr */ + 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) @@ -877,10 +932,10 @@ int32 mc = 0; uint32 i; if ((val <= 0) || (val > MAXMEMSIZE) || ((val & 07777) != 0)) - return SCPE_ARG; + 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; + return SCPE_OK; MEMSIZE = val; for (i = MEMSIZE; i < MAXMEMSIZE; i++) M[i] = 0; return SCPE_OK; @@ -894,20 +949,23 @@ int32 i, lnt; t_stat r; if (cptr == NULL) { - for (i = 0; i < hst_lnt; i++) hst[i].pc = 0; - hst_p = 0; - return SCPE_OK; } + for (i = 0; i < hst_lnt; i++) hst[i].pc = 0; + hst_p = 0; + return SCPE_OK; + } lnt = (int32) get_uint (cptr, 10, HIST_MAX, &r); if ((r != SCPE_OK) || (lnt && (lnt < HIST_MIN))) return SCPE_ARG; hst_p = 0; if (hst_lnt) { - free (hst); - hst_lnt = 0; - hst = NULL; } + free (hst); + hst_lnt = 0; + hst = NULL; + } if (lnt) { - hst = calloc (sizeof (struct InstHistory), lnt); - if (hst == NULL) return SCPE_MEM; - hst_lnt = lnt; } + hst = (InstHistory *) calloc (lnt, sizeof (InstHistory)); + if (hst == NULL) return SCPE_MEM; + hst_lnt = lnt; + } return SCPE_OK; } @@ -919,36 +977,37 @@ int32 ov, pf, op, k, di, lnt; char *cptr = (char *) desc; t_stat r; t_value sim_eval; -struct InstHistory *h; +InstHistory *h; extern t_stat fprint_sym (FILE *ofile, t_addr addr, t_value *val, - UNIT *uptr, int32 sw); + UNIT *uptr, int32 sw); -if (hst_lnt == 0) return SCPE_NOFNC; /* enabled? */ +if (hst_lnt == 0) return SCPE_NOFNC; /* enabled? */ if (cptr) { - lnt = (int32) get_uint (cptr, 10, hst_lnt, &r); - if ((r != SCPE_OK) || (lnt == 0)) return SCPE_ARG; } + lnt = (int32) get_uint (cptr, 10, hst_lnt, &r); + if ((r != SCPE_OK) || (lnt == 0)) return SCPE_ARG; + } else lnt = hst_lnt; -di = hst_p - lnt; /* work forward */ +di = hst_p - lnt; /* work forward */ if (di < 0) di = di + hst_lnt; fprintf (st, "PC OV AC IO PF EA IR\n\n"); -for (k = 0; k < lnt; k++) { /* print specified */ - h = &hst[(++di) % hst_lnt]; /* entry pointer */ - if (h->pc & HIST_PC) { /* instruction? */ - ov = (h->ovac >> HIST_V_SHF) & 1; /* overflow */ - pf = (h->pfio >> HIST_V_SHF) & 077; /* prog flags */ - op = ((h->ir >> 13) & 037); /* get opcode */ - fprintf (st, "%06o %o %06o %06o %02o ", - h->pc & AMASK, ov, h->ovac & DMASK, h->pfio & DMASK, pf); - if ((op < 032) && (op != 007)) /* mem ref instr */ - fprintf (st, "%06o ", h->ea); - else fprintf (st, " "); - sim_eval = h->ir; - if ((fprint_sym (st, h->pc & AMASK, &sim_eval, &cpu_unit, SWMASK ('M'))) > 0) - fprintf (st, "(undefined) %06o", h->ir); - else if ((op < 032) && (op != 007)) /* mem ref instr */ - fprintf (st, " [%06o]", h->opnd); - fputc ('\n', st); /* end line */ - } /* end else instruction */ - } /* end for */ +for (k = 0; k < lnt; k++) { /* print specified */ + h = &hst[(++di) % hst_lnt]; /* entry pointer */ + if (h->pc & HIST_PC) { /* instruction? */ + ov = (h->ovac >> HIST_V_SHF) & 1; /* overflow */ + pf = (h->pfio >> HIST_V_SHF) & 077; /* prog flags */ + op = ((h->ir >> 13) & 037); /* get opcode */ + fprintf (st, "%06o %o %06o %06o %02o ", + h->pc & AMASK, ov, h->ovac & DMASK, h->pfio & DMASK, pf); + if ((op < 032) && (op != 007)) /* mem ref instr */ + fprintf (st, "%06o ", h->ea); + else fprintf (st, " "); + sim_eval = h->ir; + if ((fprint_sym (st, h->pc & AMASK, &sim_eval, &cpu_unit, SWMASK ('M'))) > 0) + fprintf (st, "(undefined) %06o", h->ir); + else if ((op < 032) && (op != 007)) /* mem ref instr */ + fprintf (st, " [%06o]", h->opnd); + fputc ('\n', st); /* end line */ + } /* end else instruction */ + } /* end for */ return SCPE_OK; } diff --git a/PDP1/pdp1_defs.h b/PDP1/pdp1_defs.h index 309f93de..3887d230 100644 --- a/PDP1/pdp1_defs.h +++ b/PDP1/pdp1_defs.h @@ -1,6 +1,6 @@ /* pdp1_defs.h: 18b PDP simulator definitions - Copyright (c) 1993-2004, Robert M. Supnik + Copyright (c) 1993-2005, 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"), @@ -23,13 +23,14 @@ used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization from Robert M Supnik. - 08-Feb-04 PLB Added support for display - 08-Dec-03 RMS Added support for parallel drum - 18-Oct-03 RMS Added DECtape off reel message - 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 + 22-Jul-05 RMS Fixed definition of CPLS_DPY + 08-Feb-04 PLB Added support for display + 08-Dec-03 RMS Added support for parallel drum + 18-Oct-03 RMS Added DECtape off reel message + 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. @@ -37,99 +38,104 @@ This simulator implements the following options: - Automatic multiply/divide Type 10 - Memory extension control Type 15 - Parallel drum Type 23 - Serial drum Type 24 - Graphic display Type 30 - Line printer control Type 62 - Microtape (DECtape) control Type 550 + Automatic multiply/divide Type 10 + Memory extension control Type 15 + Parallel drum Type 23 + Serial drum Type 24 + Graphic display Type 30 + Line printer control Type 62 + Microtape (DECtape) control Type 550 */ +#ifndef _PDP1_DEFS_H_ +#define _PDP1_DEFS_H_ 0 + #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 */ -#define STOP_DTOFF 7 /* DECtape off reel */ +#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 */ +#define STOP_DTOFF 7 /* DECtape off reel */ /* 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) +#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? */ - +#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 */ +#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_V_DRP 0 /* parallel drum busy */ +#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_V_DRP 0 /* parallel drum busy */ -#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) -#define IOS_DRP (1 << IOS_V_DRP) +#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) +#define IOS_DRP (1 << IOS_V_DRP) /* Completion pulses */ -#define CPLS_V_PTR 5 -#define CPLS_V_PTP 4 -#define CPLS_V_TTO 3 -#define CPLS_V_LPT 2 -#define CPLS_V_DPY 1 -#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) -#define CPLS_DPY (1 << CPLS_V_TTY) +#define CPLS_V_PTR 5 +#define CPLS_V_PTP 4 +#define CPLS_V_TTO 3 +#define CPLS_V_LPT 2 +#define CPLS_V_DPY 1 +#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) +#define CPLS_DPY (1 << CPLS_V_DPY) /* Sequence break flags */ -#define SB_V_IP 0 /* in progress */ -#define SB_V_RQ 1 /* request */ -#define SB_V_ON 2 /* enabled */ +#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) +#define SB_IP (1 << SB_V_IP) +#define SB_RQ (1 << SB_V_RQ) +#define SB_ON (1 << SB_V_ON) + +#endif diff --git a/PDP1/pdp1_doc.txt b/PDP1/pdp1_doc.txt index 63d4fbbf..9d406710 100644 --- a/PDP1/pdp1_doc.txt +++ b/PDP1/pdp1_doc.txt @@ -7,8 +7,8 @@ Date: 15-Nov-2004 The following copyright notice applies to both the SIMH source and binary: - Original code published in 1993-2004, written by Robert M Supnik - Copyright (c) 1993-2004, Robert M Supnik + Original code published in 1993-2005, written by Robert M Supnik + Copyright (c) 1993-2005, 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"), @@ -27,8 +27,8 @@ The following copyright notice applies to both the SIMH source and binary: 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 + 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. diff --git a/PDP1/pdp1_drm.c b/PDP1/pdp1_drm.c index de47fe50..f8669e27 100644 --- a/PDP1/pdp1_drm.c +++ b/PDP1/pdp1_drm.c @@ -1,6 +1,6 @@ /* pdp1_drm.c: PDP-1 drum simulator - Copyright (c) 1993-2004, Robert M Supnik + Copyright (c) 1993-2005, 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"), @@ -19,18 +19,18 @@ 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 + 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. - drp Type 23 parallel drum - drm Type 24 serial drum + drp Type 23 parallel drum + drm Type 24 serial drum - 08-Dec-03 RMS Added parallel drum support - Fixed bug in DBL/DCN decoding - 26-Oct-03 RMS Cleaned up buffer copy code - 23-Jul-03 RMS Fixed incorrect logical, missing activate - 05-Dec-02 RMS Cloned from pdp18b_drm.c + 08-Dec-03 RMS Added parallel drum support + Fixed bug in DBL/DCN decoding + 26-Oct-03 RMS Cleaned up buffer copy code + 23-Jul-03 RMS Fixed incorrect logical, missing activate + 05-Dec-02 RMS Cloned from pdp18b_drm.c */ #include "pdp1_defs.h" @@ -38,38 +38,38 @@ /* Serial drum constants */ -#define DRM_NUMWDS 256 /* words/sector */ -#define DRM_NUMSC 2 /* sectors/track */ -#define DRM_NUMTR 256 /* tracks/drum */ -#define DRM_NUMWDT (DRM_NUMWDS * DRM_NUMSC) /* words/track */ -#define DRM_SIZE (DRM_NUMTR * DRM_NUMWDT) /* words/drum */ -#define DRM_SMASK ((DRM_NUMTR * DRM_NUMSC) - 1) /* sector mask */ +#define DRM_NUMWDS 256 /* words/sector */ +#define DRM_NUMSC 2 /* sectors/track */ +#define DRM_NUMTR 256 /* tracks/drum */ +#define DRM_NUMWDT (DRM_NUMWDS * DRM_NUMSC) /* words/track */ +#define DRM_SIZE (DRM_NUMTR * DRM_NUMWDT) /* words/drum */ +#define DRM_SMASK ((DRM_NUMTR * DRM_NUMSC) - 1) /* sector mask */ /* Parallel drum constants */ -#define DRP_NUMWDT 4096 /* words/track */ -#define DRP_NUMTK 32 /* tracks/drum */ -#define DRP_SIZE (DRP_NUMWDT * DRP_NUMTK) /* words/drum */ -#define DRP_V_RWE 17 /* read/write enable */ -#define DRP_V_FLD 12 /* drum field */ -#define DRP_M_FLD 037 -#define DRP_TAMASK 07777 /* track address */ -#define DRP_WCMASK 07777 /* word count */ -#define DRP_MAINCM 07777 /* mem addr incr */ -#define DRP_GETRWE(x) (((x) >> DRP_V_RWE) & 1) -#define DRP_GETRWF(x) (((x) >> DRP_V_FLD) & DRP_M_FLD) +#define DRP_NUMWDT 4096 /* words/track */ +#define DRP_NUMTK 32 /* tracks/drum */ +#define DRP_SIZE (DRP_NUMWDT * DRP_NUMTK) /* words/drum */ +#define DRP_V_RWE 17 /* read/write enable */ +#define DRP_V_FLD 12 /* drum field */ +#define DRP_M_FLD 037 +#define DRP_TAMASK 07777 /* track address */ +#define DRP_WCMASK 07777 /* word count */ +#define DRP_MAINCM 07777 /* mem addr incr */ +#define DRP_GETRWE(x) (((x) >> DRP_V_RWE) & 1) +#define DRP_GETRWF(x) (((x) >> DRP_V_FLD) & DRP_M_FLD) /* Parameters in the unit descriptor */ -#define FUNC u4 /* function */ -#define DRM_READ 000 /* read */ -#define DRM_WRITE 010 /* write */ -#define DRP_RW 000 /* read/write */ -#define DRP_BRK 001 /* break on address */ +#define FUNC u4 /* function */ +#define DRM_READ 000 /* read */ +#define DRM_WRITE 010 /* write */ +#define DRP_RW 000 /* read/write */ +#define DRP_BRK 001 /* break on address */ + +#define GET_POS(x) ((int) fmod (sim_gtime() / ((double) (x)), \ + ((double) DRM_NUMWDT))) -#define GET_POS(x) ((int) fmod (sim_gtime() / ((double) (x)), \ - ((double) DRM_NUMWDT))) - extern int32 M[]; extern int32 iosta, sbs; extern int32 stop_inst; @@ -77,25 +77,25 @@ extern UNIT cpu_unit; /* Serial drum variables */ -uint32 drm_da = 0; /* track address */ -uint32 drm_ma = 0; /* memory address */ -uint32 drm_err = 0; /* error flag */ -uint32 drm_wlk = 0; /* write lock */ -int32 drm_time = 4; /* inter-word time */ -int32 drm_stopioe = 1; /* stop on error */ +uint32 drm_da = 0; /* track address */ +uint32 drm_ma = 0; /* memory address */ +uint32 drm_err = 0; /* error flag */ +uint32 drm_wlk = 0; /* write lock */ +int32 drm_time = 4; /* inter-word time */ +int32 drm_stopioe = 1; /* stop on error */ /* Parallel drum variables */ -uint32 drp_rde = 0; /* read enable */ -uint32 drp_wre = 0; /* write enable */ -uint32 drp_rdf = 0; /* read field */ -uint32 drp_wrf = 0; /* write field */ -uint32 drp_ta = 0; /* track address */ -uint32 drp_wc = 0; /* word count */ -uint32 drp_ma = 0; /* memory address */ -uint32 drp_err = 0; /* error */ -int32 drp_time = 2; /* inter-word time */ -int32 drp_stopioe = 1; /* stop on error */ +uint32 drp_rde = 0; /* read enable */ +uint32 drp_wre = 0; /* write enable */ +uint32 drp_rdf = 0; /* read field */ +uint32 drp_wrf = 0; /* write field */ +uint32 drp_ta = 0; /* track address */ +uint32 drp_wc = 0; /* word count */ +uint32 drp_ma = 0; /* memory address */ +uint32 drp_err = 0; /* error */ +int32 drp_time = 2; /* inter-word time */ +int32 drp_stopioe = 1; /* stop on error */ /* Forward declarations */ @@ -106,64 +106,70 @@ t_stat drp_reset (DEVICE *dptr); /* DRM data structures - drm_dev DRM device descriptor - drm_unit DRM unit descriptor - drm_reg DRM register list + 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) }; +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 } }; + { 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 }; + "DRM", &drm_unit, drm_reg, NULL, + 1, 8, 20, 1, 8, 18, + NULL, NULL, &drm_reset, + NULL, NULL, NULL, + NULL, DEV_DISABLE + }; /* DRP data structures - drp_dev DRP device descriptor - drp_unit DRP unit descriptor - drp_reg DRP register list + drp_dev DRP device descriptor + drp_unit DRP unit descriptor + drp_reg DRP register list */ -UNIT drp_unit = - { UDATA (&drp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_BUFABLE+UNIT_MUSTBUF, - DRM_SIZE) }; +UNIT drp_unit = { + UDATA (&drp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_BUFABLE+UNIT_MUSTBUF, + DRM_SIZE) + }; REG drp_reg[] = { - { ORDATA (TA, drp_ta, 12) }, - { ORDATA (RDF, drp_rdf, 5) }, - { FLDATA (RDE, drp_rde, 0) }, - { FLDATA (WRF, drp_wrf, 5) }, - { FLDATA (WRE, drp_wre, 0) }, - { ORDATA (MA, drp_ma, 16) }, - { ORDATA (WC, drp_wc, 12) }, - { FLDATA (BUSY, iosta, IOS_V_DRP) }, - { FLDATA (ERR, drp_err, 0) }, - { DRDATA (TIME, drp_time, 24), REG_NZ + PV_LEFT }, - { FLDATA (STOP_IOE, drp_stopioe, 0) }, - { NULL } }; + { ORDATA (TA, drp_ta, 12) }, + { ORDATA (RDF, drp_rdf, 5) }, + { FLDATA (RDE, drp_rde, 0) }, + { FLDATA (WRF, drp_wrf, 5) }, + { FLDATA (WRE, drp_wre, 0) }, + { ORDATA (MA, drp_ma, 16) }, + { ORDATA (WC, drp_wc, 12) }, + { FLDATA (BUSY, iosta, IOS_V_DRP) }, + { FLDATA (ERR, drp_err, 0) }, + { DRDATA (TIME, drp_time, 24), REG_NZ + PV_LEFT }, + { FLDATA (STOP_IOE, drp_stopioe, 0) }, + { NULL } + }; DEVICE drp_dev = { - "DRP", &drp_unit, drp_reg, NULL, - 1, 8, 20, 1, 8, 18, - NULL, NULL, &drp_reset, - NULL, NULL, NULL, - NULL, DEV_DISABLE | DEV_DIS }; - + "DRP", &drp_unit, drp_reg, NULL, + 1, 8, 20, 1, 8, 18, + NULL, NULL, &drp_reset, + NULL, NULL, NULL, + NULL, DEV_DISABLE | DEV_DIS + }; + /* IOT routines */ int32 drm (int32 IR, int32 dev, int32 dat) @@ -171,71 +177,85 @@ int32 drm (int32 IR, int32 dev, int32 dat) int32 t; int32 pulse = (IR >> 6) & 037; -if ((drm_dev.flags & DEV_DIS) == 0) { /* serial enabled? */ - 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 & AMASK; /* load mem addr */ - drm_unit.FUNC = pulse & DRM_WRITE; /* save function */ - break; - case 062: /* DBL, DCN */ - if ((pulse & 010) == 0) /* DBL? */ - 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); - } /* end case */ - return dat; } /* end if serial */ +if ((drm_dev.flags & DEV_DIS) == 0) { /* serial enabled? */ + if ((pulse != 001) && (pulse != 011)) /* invalid pulse? */ + return (stop_inst << IOT_V_REASON) | dat; /* stop if requested */ + switch (dev) { /* switch on device */ -if ((drp_dev.flags & DEV_DIS) == 0) { /* parallel enabled? */ - switch (dev) { /* switch on device */ - case 061: /* DIA, DBA */ - drp_err = 0; /* clear error */ - iosta = iosta & ~IOS_DRP; /* not busy */ - drp_rde = DRP_GETRWE (dat); /* set read enable */ - drp_rdf = DRP_GETRWF (dat); /* set read field */ - drp_ta = dat & DRP_TAMASK; /* set track addr */ - if (IR & 02000) { /* DBA? */ - t = drp_ta - GET_POS (drp_time); /* delta words */ - if (t <= 0) t = t + DRP_NUMWDT; /* wrap around? */ - sim_activate (&drp_unit, t); /* start operation */ - drp_unit.FUNC = DRP_BRK; } /* mark as break */ - else drp_unit.FUNC = DRP_RW; /* no, read/write */ - break; - case 062: /* DWC, DRA */ - if (IR & 02000) dat = GET_POS (drp_time) | /* DRA, get position */ - (drp_err? 0400000: 0); - else { /* DWC */ - drp_wre = DRP_GETRWE (dat); /* set write enable */ - drp_wrf = DRP_GETRWF (dat); /* set write field */ - drp_wc = dat & DRP_WCMASK; } /* set word count */ - break; - case 063: /* DCL */ - drp_ma = dat & AMASK; /* set mem address */ - t = drp_ta - GET_POS (drp_time); /* delta words */ - if (t <= 0) t = t + DRP_NUMWDT; /* wrap around? */ - sim_activate (&drp_unit, t); /* start operation */ - iosta = iosta | IOS_DRP; /* set busy */ - break; - case 064: /* not assigned */ - return (stop_inst << IOT_V_REASON) | dat; /* stop if requested */ - } /* end case */ - return dat; } /* end if parallel */ + case 061: /* DWR, DRD */ + drm_ma = dat & AMASK; /* load mem addr */ + drm_unit.FUNC = pulse & DRM_WRITE; /* save function */ + break; -return (stop_inst << IOT_V_REASON) | dat; /* stop if requested */ + case 062: /* DBL, DCN */ + if ((pulse & 010) == 0) /* DBL? */ + 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); + } /* end case */ + + return dat; + } /* end if serial */ + +if ((drp_dev.flags & DEV_DIS) == 0) { /* parallel enabled? */ + switch (dev) { /* switch on device */ + + case 061: /* DIA, DBA */ + drp_err = 0; /* clear error */ + iosta = iosta & ~IOS_DRP; /* not busy */ + drp_rde = DRP_GETRWE (dat); /* set read enable */ + drp_rdf = DRP_GETRWF (dat); /* set read field */ + drp_ta = dat & DRP_TAMASK; /* set track addr */ + if (IR & 02000) { /* DBA? */ + t = drp_ta - GET_POS (drp_time); /* delta words */ + if (t <= 0) t = t + DRP_NUMWDT; /* wrap around? */ + sim_activate (&drp_unit, t); /* start operation */ + drp_unit.FUNC = DRP_BRK; /* mark as break */ + } + else drp_unit.FUNC = DRP_RW; /* no, read/write */ + break; + + case 062: /* DWC, DRA */ + if (IR & 02000) dat = GET_POS (drp_time) | /* DRA, get position */ + (drp_err? 0400000: 0); + else { /* DWC */ + drp_wre = DRP_GETRWE (dat); /* set write enable */ + drp_wrf = DRP_GETRWF (dat); /* set write field */ + drp_wc = dat & DRP_WCMASK; /* set word count */ + } + break; + + case 063: /* DCL */ + drp_ma = dat & AMASK; /* set mem address */ + t = drp_ta - GET_POS (drp_time); /* delta words */ + if (t <= 0) t = t + DRP_NUMWDT; /* wrap around? */ + sim_activate (&drp_unit, t); /* start operation */ + iosta = iosta | IOS_DRP; /* set busy */ + break; + + case 064: /* not assigned */ + return (stop_inst << IOT_V_REASON) | dat; /* stop if requested */ + } /* end case */ + + return dat; + } /* end if parallel */ + +return (stop_inst << IOT_V_REASON) | dat; /* stop if requested */ } - + /* Serial unit service - this code assumes the entire drum is buffered */ t_stat drm_svc (UNIT *uptr) @@ -243,26 +263,31 @@ t_stat drm_svc (UNIT *uptr) uint32 i, da; uint32 *fbuf = uptr->filebuf; -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); } +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) { /* read? */ - if (MEM_ADDR_OK (drm_ma)) /* if !nxm */ - M[drm_ma] = fbuf[da]; } /* read word */ - else { /* write */ - if ((drm_wlk >> (drm_da >> 4)) & 1) drm_err = 1; - else { /* not locked */ - fbuf[da] = M[drm_ma]; /* write word */ - if (da >= uptr->hwmark) uptr->hwmark = da + 1; } } - drm_ma = (drm_ma + 1) & AMASK; } /* 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 */ +da = drm_da * DRM_NUMWDS; /* compute dev addr */ +for (i = 0; i < DRM_NUMWDS; i++, da++) { /* do transfer */ + if (uptr->FUNC == DRM_READ) { /* read? */ + if (MEM_ADDR_OK (drm_ma)) /* if !nxm */ + M[drm_ma] = fbuf[da]; /* read word */ + } + else { /* write */ + if ((drm_wlk >> (drm_da >> 4)) & 1) drm_err = 1; + else { /* not locked */ + fbuf[da] = M[drm_ma]; /* write word */ + if (da >= uptr->hwmark) uptr->hwmark = da + 1; + } + } + drm_ma = (drm_ma + 1) & AMASK; /* 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; } @@ -271,14 +296,14 @@ return SCPE_OK; t_stat drm_reset (DEVICE *dptr) { if ((drm_dev.flags & DEV_DIS) == 0) - drp_dev.flags = drp_dev.flags | DEV_DIS; + drp_dev.flags = drp_dev.flags | DEV_DIS; drm_da = drm_ma = drm_err = 0; iosta = iosta & ~IOS_DRM; sim_cancel (&drm_unit); drm_unit.FUNC = 0; return SCPE_OK; } - + /* Parallel unit service - this code assumes the entire drum is buffered */ t_stat drp_svc (UNIT *uptr) @@ -286,25 +311,26 @@ t_stat drp_svc (UNIT *uptr) uint32 i, lim; uint32 *fbuf = uptr->filebuf; -if ((uptr->flags & UNIT_BUF) == 0) { /* not buf? abort */ - drp_err = 1; /* set error */ - iosta = iosta & ~IOS_DRP; /* clear busy */ - if (uptr->FUNC) sbs = sbs | SB_RQ; /* req intr */ - return IORETURN (drp_stopioe, SCPE_UNATT); } +if ((uptr->flags & UNIT_BUF) == 0) { /* not buf? abort */ + drp_err = 1; /* set error */ + iosta = iosta & ~IOS_DRP; /* clear busy */ + if (uptr->FUNC) sbs = sbs | SB_RQ; /* req intr */ + return IORETURN (drp_stopioe, SCPE_UNATT); + } -if (uptr->FUNC == DRP_RW) { /* read/write? */ - lim = drp_wc? drp_wc: DRP_TAMASK + 1; /* eff word count */ - for (i = 0; i < lim; i++) { /* do transfer */ - if (drp_wre) /* write enabled? */ - fbuf[(drp_wrf << DRP_V_FLD) | drp_ta] = M[drp_ma]; - if (drp_rde && MEM_ADDR_OK (drp_ma)) /* read enabled? */ - M[drp_ma] = fbuf[(drp_rdf << DRP_V_FLD) | drp_ta]; - drp_ta = (drp_ta + 1) & DRP_TAMASK; /* incr track addr */ - drp_ma = ((drp_ma & ~DRP_MAINCM) | ((drp_ma + 1) & DRP_MAINCM)); - } /* end for */ - } /* end if */ -iosta = iosta & ~IOS_DRP; /* clear busy */ -if (uptr->FUNC) sbs = sbs | SB_RQ; /* req intr */ +if (uptr->FUNC == DRP_RW) { /* read/write? */ + lim = drp_wc? drp_wc: DRP_TAMASK + 1; /* eff word count */ + for (i = 0; i < lim; i++) { /* do transfer */ + if (drp_wre) /* write enabled? */ + fbuf[(drp_wrf << DRP_V_FLD) | drp_ta] = M[drp_ma]; + if (drp_rde && MEM_ADDR_OK (drp_ma)) /* read enabled? */ + M[drp_ma] = fbuf[(drp_rdf << DRP_V_FLD) | drp_ta]; + drp_ta = (drp_ta + 1) & DRP_TAMASK; /* incr track addr */ + drp_ma = ((drp_ma & ~DRP_MAINCM) | ((drp_ma + 1) & DRP_MAINCM)); + } /* end for */ + } /* end if */ +iosta = iosta & ~IOS_DRP; /* clear busy */ +if (uptr->FUNC) sbs = sbs | SB_RQ; /* req intr */ return SCPE_OK; } @@ -313,7 +339,7 @@ return SCPE_OK; t_stat drp_reset (DEVICE *dptr) { if ((drp_dev.flags & DEV_DIS) == 0) - drm_dev.flags = drm_dev.flags | DEV_DIS; + drm_dev.flags = drm_dev.flags | DEV_DIS; drp_ta = 0; drp_rde = drp_rdf = drp_wre = drp_wrf = 0; drp_err = 0; diff --git a/PDP1/pdp1_dt.c b/PDP1/pdp1_dt.c index add68055..69c95a88 100644 --- a/PDP1/pdp1_dt.c +++ b/PDP1/pdp1_dt.c @@ -1,6 +1,6 @@ /* pdp1_dt.c: 18b DECtape simulator - Copyright (c) 1993-2004, Robert M Supnik + Copyright (c) 1993-2005, 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"), @@ -19,28 +19,29 @@ 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 + 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 + dt Type 550/555 DECtape - 25-Jan-04 RMS Revised for device debug support - 09-Jan-04 RMS Changed sim_fsize calling sequence, added STOP_OFFR - 26-Oct-03 RMS Cleaned up buffer copy code - 18-Oct-03 RMS Added DECtape off reel message, simplified timing - 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 + 16-Aug-05 RMS Fixed C++ declaration and cast problems + 25-Jan-04 RMS Revised for device debug support + 09-Jan-04 RMS Changed sim_fsize calling sequence, added STOP_OFFR + 26-Oct-03 RMS Cleaned up buffer copy code + 18-Oct-03 RMS Added DECtape off reel message, simplified timing + 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] + 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. @@ -48,13 +49,13 @@ Tape density is nominally 300 lines per inch. The format of a DECtape (as taken from the TD8E formatter) is: - reverse end zone 8192 reverse end zone codes ~ 10 feet - reverse buffer 200 interblock codes - block 0 - : - block n - forward buffer 200 interblock codes - forward end zone 8192 forward end zone codes ~ 10 feet + reverse end zone 8192 reverse end zone codes ~ 10 feet + reverse buffer 200 interblock codes + block 0 + : + block n + forward buffer 200 interblock codes + forward end zone 8192 forward end zone codes ~ 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 @@ -68,15 +69,15 @@ 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 checksum (for reverse reads) - : - trailer word 4 checksum (for forward reads) - trailer words 3,2 0 - trailer word 1 block number (for reverse reads) - trailer word 0 0 + header word 0 0 + header word 1 block number (for forward reads) + header words 2,3 0 + header word 4 checksum (for reverse reads) + : + trailer word 4 checksum (for forward reads) + 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. @@ -89,163 +90,163 @@ #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 */ +#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_LPERMC 6 /* lines per mark track */ -#define DT_BLKWD 1 /* blk no word in h/t */ -#define DT_CSMWD 4 /* checksum word in h/t */ -#define DT_HTWRD 5 /* header/trailer words */ -#define DT_EZLIN (8192 * DT_LPERMC) /* end zone length */ -#define DT_BFLIN (200 * DT_LPERMC) /* buffer length */ -#define DT_BLKLN (DT_BLKWD * DT_LPERMC) /* blk no line in h/t */ -#define DT_CSMLN (DT_CSMWD * DT_LPERMC) /* csum line in h/t */ -#define DT_HTLIN (DT_HTWRD * DT_LPERMC) /* header/trailer lines */ +#define DT_LPERMC 6 /* lines per mark track */ +#define DT_BLKWD 1 /* blk no word in h/t */ +#define DT_CSMWD 4 /* checksum word in h/t */ +#define DT_HTWRD 5 /* header/trailer words */ +#define DT_EZLIN (8192 * DT_LPERMC) /* end zone length */ +#define DT_BFLIN (200 * DT_LPERMC) /* buffer length */ +#define DT_BLKLN (DT_BLKWD * DT_LPERMC) /* blk no line in h/t */ +#define DT_CSMLN (DT_CSMWD * DT_LPERMC) /* csum line in h/t */ +#define DT_HTLIN (DT_HTWRD * DT_LPERMC) /* header/trailer lines */ /* 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)) +#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_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)) +#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 +#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 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)) +#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_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) +#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) +#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_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) + ((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) + ((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 */ +#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_BL 004 /* block # lblk */ +#define LOG_MS 001 /* move, search */ +#define LOG_RW 002 /* read write */ +#define LOG_BL 004 /* block # lblk */ + +#define ABS(x) (((x) < 0)? (-(x)): (x)) -#define ABS(x) (((x) < 0)? (-(x)): (x)) - extern int32 M[]; extern int32 sbs; extern int32 stop_inst; @@ -254,17 +255,18 @@ extern int32 sim_switches; extern int32 sim_is_running; extern FILE *sim_deb; -int32 dtsa = 0; /* status A */ -int32 dtsb = 0; /* status B */ -int32 dtdb = 0; /* data buffer */ -int32 dt_ltime = 12; /* interline time */ -int32 dt_dctime = 40000; /* decel time */ +int32 dtsa = 0; /* status A */ +int32 dtsb = 0; /* status B */ +int32 dtdb = 0; /* data buffer */ +int32 dt_ltime = 12; /* interline time */ +int32 dt_dctime = 40000; /* decel time */ int32 dt_substate = 0; int32 dt_logblk = 0; int32 dt_stopoffr = 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 }; +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); @@ -282,116 +284,129 @@ 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 + 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) } }; + { 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 (DCTIME, dt_dctime, 31), REG_NZ }, - { ORDATA (SUBSTATE, dt_substate, 2) }, - { 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) }, - { FLDATA (STOP_OFFR, dt_stopoffr, 0) }, - { NULL } }; + { 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 (DCTIME, dt_dctime, 31), REG_NZ }, + { ORDATA (SUBSTATE, dt_substate, 2) }, + { 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) }, + { FLDATA (STOP_OFFR, dt_stopoffr, 0) }, + { 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 } }; + { 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 } + }; DEBTAB dt_deb[] = { - { "MOTION", LOG_MS }, - { "DATA", LOG_RW }, - { "BLOCK", LOG_BL }, - { NULL, 0 } }; + { "MOTION", LOG_MS }, + { "DATA", LOG_RW }, + { "BLOCK", LOG_BL }, + { 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 | DEV_DEBUG, 0, - dt_deb, NULL, NULL }; - + "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 | DEV_DEBUG, 0, + dt_deb, NULL, NULL + }; + +/* IOT routine */ + 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 (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; } +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) @@ -399,36 +414,36 @@ 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_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); +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 + - schedule acceleration + - set function as next state 2. If change in motion, start to stop - - if not already decelerating (could be reversing), - schedule deceleration + - 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 + - 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 + - schedule acceleration + - set function as next state 5. If not yet at speed, - - set function as next state + - set function as next state 6. If at speed, - - set function as current state, schedule function + - set function as current state, schedule function */ void dt_newsa (int32 newf) @@ -437,63 +452,71 @@ 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? */ +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 ((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 ((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_dctime - (dt_dctime >> 2)); /* sched accel */ - DTS_SETSTA (DTS_ACCF | new_dir, 0); /* state = accel */ - DTS_SET2ND (DTS_ATSF | new_dir, new_fnc); /* next = fnc */ - return; } +if (new_mving & ~prev_mving) { /* start? */ + if (dt_setpos (uptr)) return; /* update pos */ + sim_cancel (uptr); /* stop current */ + sim_activate (uptr, dt_dctime - (dt_dctime >> 2)); /* sched 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_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_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_dctime - (dt_dctime >> 2)); /* sched 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_ACCF) { /* not accel/at speed? */ + if (dt_setpos (uptr)) return; /* update pos */ + sim_cancel (uptr); /* cancel cur */ + sim_activate (uptr, dt_dctime - (dt_dctime >> 2)); /* sched 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; } +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; +return; } - + /* Schedule new DECtape function This routine is only called if @@ -511,78 +534,89 @@ 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 */ +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); +unum = (int32) (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 (DEBUG_PRI (dt_dev, LOG_MS)) fprintf (sim_deb, ">>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 (DEBUG_PRI (dt_dev, LOG_MS)) fprintf (sim_deb, ">>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 (DEBUG_PRI (dt_dev, LOG_RW) || - (DEBUG_PRI (dt_dev, LOG_BL) && (blk == dt_logblk))) - fprintf (sim_deb, ">>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; } +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 (DEBUG_PRI (dt_dev, LOG_MS)) fprintf (sim_deb, ">>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 (DEBUG_PRI (dt_dev, LOG_MS)) fprintf (sim_deb, ">>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 (DEBUG_PRI (dt_dev, LOG_RW) || + (DEBUG_PRI (dt_dev, LOG_BL) && (blk == dt_logblk))) + fprintf (sim_deb, ">>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) + 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) + 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. @@ -594,40 +628,47 @@ 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_dctime - (dt_dctime >> 2)) / 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 */ +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_dctime - (dt_dctime >> 2)) / 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? */ + 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; } + unum = (int32) (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 @@ -638,8 +679,7 @@ t_stat dt_svc (UNIT *uptr) int32 mot = DTS_GETMOT (uptr->STATE); int32 dir = mot & DTS_DIR; int32 fnc = DTS_GETFNC (uptr->STATE); -int32 *fbuf = uptr->filebuf; -int32 unum = uptr - dt_dev.units; +int32 *fbuf = (int32 *) uptr->filebuf; int32 blk, wrd, ma, relpos; uint32 ba; @@ -651,21 +691,26 @@ uint32 ba; */ switch (mot) { -case DTS_DECF: case DTS_DECR: /* decelerating */ - if (dt_setpos (uptr)) /* upd pos; off reel? */ - return IORETURN (dt_stopoffr, STOP_DTOFF); - uptr->STATE = DTS_NXTSTA (uptr->STATE); /* advance state */ - if (uptr->STATE) /* not stopped? */ - sim_activate (uptr, dt_dctime - (dt_dctime >> 2)); /* 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; } + + case DTS_DECF: case DTS_DECR: /* decelerating */ + if (dt_setpos (uptr)) /* upd pos; off reel? */ + return IORETURN (dt_stopoffr, STOP_DTOFF); + uptr->STATE = DTS_NXTSTA (uptr->STATE); /* advance state */ + if (uptr->STATE) /* not stopped? */ + sim_activate (uptr, dt_dctime - (dt_dctime >> 2)); /* 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 @@ -674,96 +719,109 @@ default: /* other */ Off reel - detach unit (it must be deselected) */ -if (dt_setpos (uptr)) /* upd pos; off reel? */ - return IORETURN (dt_stopoffr, STOP_DTOFF); -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; - +if (dt_setpos (uptr)) /* upd pos; off reel? */ + return IORETURN (dt_stopoffr, STOP_DTOFF); +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; + 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 = fbuf[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; + 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 = fbuf[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) fbuf[ba] = dt_comobv (dtdb); /* get data word */ - else fbuf[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; + 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) fbuf[ba] = dt_comobv (dtdb); /* get data word */ + else fbuf[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 */ + default: + dt_seterr (uptr, DTB_SEL); /* impossible state */ + break; + } + +DT_UPDINT; /* update interrupts */ return SCPE_OK; } - + /* Utility routines */ /* Set error flag */ @@ -772,13 +830,14 @@ 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 */ +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; } @@ -789,8 +848,8 @@ 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 */ +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; } @@ -799,10 +858,10 @@ return; int32 dt_comobv (int32 dat) { -dat = dat ^ 0777777; /* compl obverse */ +dat = dat ^ 0777777; /* compl obverse */ dat = ((dat >> 15) & 07) | ((dat >> 9) & 070) | - ((dat >> 3) & 0700) | ((dat & 0700) << 3) | - ((dat & 070) << 9) | ((dat & 07) << 15); + ((dat >> 3) & 0700) | ((dat & 0700) << 3) | + ((dat & 070) << 9) | ((dat & 07) << 15); return dat; } @@ -810,16 +869,17 @@ return dat; int32 dt_csum (UNIT *uptr, int32 blk) { -int32 *fbuf = uptr->filebuf; +int32 *fbuf = (int32 *) 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 = fbuf[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 */ +for (i = 0; i < DTU_BSIZE (uptr); i++) { /* loop thru buf */ + wrd = fbuf[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 */ @@ -828,15 +888,15 @@ 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 */ +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) @@ -844,22 +904,25 @@ 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 */ +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; } @@ -873,7 +936,7 @@ return ((dtsb & (DTB_ERF | DTB_DTF))? IOS_DTA: 0); return 0; #endif } - + /* Attach routine Determine 12b, 16b, or 18b/36b format @@ -891,57 +954,64 @@ uint32 ba, sz, k, *fbuf; 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 (uptr->fileref))) { - 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; } -fbuf = uptr->filebuf; /* file buffer */ +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 (uptr->fileref))) { + 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 (uint32)); +if (uptr->filebuf == NULL) { /* can't alloc? */ + detach_unit (uptr); + return SCPE_MEM; + } +fbuf = (uint32 *) 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 */ - fbuf[ba] = ((uint32) (pdp8b[k] & 07777) << 6) | - ((uint32) (pdp8b[k + 1] >> 6) & 077); - fbuf[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++) - fbuf[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 */ +if (uptr->flags & UNIT_8FMT) { /* 12b? */ + for (ba = 0; ba < uptr->capac; ) { /* loop thru file */ + k = fxread (pdp8b, sizeof (uint16), 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 */ + fbuf[ba] = ((uint32) (pdp8b[k] & 07777) << 6) | + ((uint32) (pdp8b[k + 1] >> 6) & 077); + fbuf[ba + 1] = ((uint32) (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 (uint16), D18_BSIZE, uptr->fileref); + if (k == 0) break; + for ( ; k < D18_BSIZE; k++) pdp11b[k] = 0; + for (k = 0; k < D18_BSIZE; k++) + fbuf[ba++] = pdp11b[k]; + } + uptr->hwmark = ba; /* end elif */ + } +else uptr->hwmark = fxread (uptr->filebuf, sizeof (uint32), + 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; } @@ -961,42 +1031,48 @@ uint16 pdp11b[D18_BSIZE]; uint32 ba, k, *fbuf; int32 u = uptr - dt_dev.units; -if (!(uptr->flags & UNIT_ATT)) return SCPE_OK; /* attached? */ +if (!(uptr->flags & UNIT_ATT)) return SCPE_OK; /* attached? */ 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; } -fbuf = 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] = (fbuf[ba] >> 6) & 07777; - pdp8b[k + 1] = ((fbuf[ba] & 077) << 6) | - ((fbuf[ba + 1] >> 12) & 077); - pdp8b[k + 2] = fbuf[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] = fbuf[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 */ + 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; + } +fbuf = (uint32 *) 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] = (fbuf[ba] >> 6) & 07777; + pdp8b[k + 1] = ((fbuf[ba] & 077) << 6) | + ((fbuf[ba + 1] >> 12) & 077); + pdp8b[k + 2] = fbuf[ba + 1] & 07777; + ba = ba + 2; + } /* end loop blk */ + fxwrite (pdp8b, sizeof (uint16), 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] = fbuf[ba++] & 0177777; + fxwrite (pdp11b, sizeof (uint16), D18_BSIZE, uptr->fileref); + if (ferror (uptr->fileref)) break; + } /* end loop file */ + } /* end if 16b */ + else fxwrite (uptr->filebuf, sizeof (uint32), /* 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 index c41451bd..faea4467 100644 --- a/PDP1/pdp1_lp.c +++ b/PDP1/pdp1_lp.c @@ -1,6 +1,6 @@ /* pdp1_lp.c: PDP-1 line printer simulator - Copyright (c) 1993-2004, Robert M. Supnik + Copyright (c) 1993-2005, 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"), @@ -19,36 +19,37 @@ 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 + Except as contained in this notice, the name of Robert M Supnik shall not be + bused 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 + 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 + 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 */ +#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 */ +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','*','.','+',']','|','[' }; + ' ','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; @@ -58,112 +59,127 @@ t_stat lpt_reset (DEVICE *dptr); /* LPT data structures - lpt_dev LPT device descriptor - lpt_unit LPT unit - lpt_reg LPT register list + 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 }; + 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 } }; + { 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 }; - + "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 */ +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 */ +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 + 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" }; + "\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 ((uptr->flags & UNIT_ATT) == 0) /* attached? */ - return IORETURN (lpt_stopioe, SCPE_UNATT); - fputs (lpt_cc[lpt_spc & 07], uptr->fileref); /* print cctl */ - if (ferror (uptr->fileref)) { /* error? */ - perror ("LPT I/O error"); - clearerr (uptr->fileref); - return SCPE_IOERR; } - lpt_ovrpr = 0; } /* dont overprint */ -else { iosta = iosta | IOS_PNT; /* print */ - if ((uptr->flags & UNIT_ATT) == 0) /* attached? */ - return IORETURN (lpt_stopioe, SCPE_UNATT); - if (lpt_ovrpr) fputc ('\r', uptr->fileref); /* overprint? */ - fputs (lpt_buf, uptr->fileref); /* print buffer */ - if (ferror (uptr->fileref)) { /* test error */ - perror ("LPT I/O error"); - clearerr (uptr->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 (uptr->fileref); /* update position */ +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 ((uptr->flags & UNIT_ATT) == 0) /* attached? */ + return IORETURN (lpt_stopioe, SCPE_UNATT); + fputs (lpt_cc[lpt_spc & 07], uptr->fileref); /* print cctl */ + if (ferror (uptr->fileref)) { /* error? */ + perror ("LPT I/O error"); + clearerr (uptr->fileref); + return SCPE_IOERR; + } + lpt_ovrpr = 0; /* dont overprint */ + } +else { + iosta = iosta | IOS_PNT; /* print */ + if ((uptr->flags & UNIT_ATT) == 0) /* attached? */ + return IORETURN (lpt_stopioe, SCPE_UNATT); + if (lpt_ovrpr) fputc ('\r', uptr->fileref); /* overprint? */ + fputs (lpt_buf, uptr->fileref); /* print buffer */ + if (ferror (uptr->fileref)) { /* test error */ + perror ("LPT I/O error"); + clearerr (uptr->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 (uptr->fileref); /* update position */ return SCPE_OK; } @@ -173,12 +189,12 @@ 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 */ +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 */ +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 index 4e84bbac..c19a9ce9 100644 --- a/PDP1/pdp1_stddev.c +++ b/PDP1/pdp1_stddev.c @@ -1,6 +1,6 @@ /* pdp1_stddev.c: PDP-1 standard devices - Copyright (c) 1993-2004, Robert M. Supnik + Copyright (c) 1993-2005, 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"), @@ -19,30 +19,30 @@ 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 + 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 + ptr paper tape reader + ptp paper tape punch + tti keyboard + tto teleprinter - 29-Oct-03 RMS Added PTR FIODEC-to-ASCII translation (from Phil Budne) - 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 + 29-Oct-03 RMS Added PTR FIODEC-to-ASCII translation (from Phil Budne) + 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 Note: PTP timeout must be >10X faster that TTY output timeout for Macro to work correctly! @@ -50,30 +50,30 @@ #include "pdp1_defs.h" -#define FIODEC_STOP 013 /* stop code */ -#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 -#define UNIT_V_ASCII (UNIT_V_UF + 0) /* ASCII/binary mode */ -#define UNIT_ASCII (1 << UNIT_V_ASCII) -#define PTR_LEADER 20 /* ASCII leader chars */ +#define FIODEC_STOP 013 /* stop code */ +#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 +#define UNIT_V_ASCII (UNIT_V_UF + 0) /* ASCII/binary mode */ +#define UNIT_ASCII (1 << UNIT_V_ASCII) +#define PTR_LEADER 20 /* ASCII leader chars */ int32 ptr_state = 0; int32 ptr_wait = 0; int32 ptr_stopioe = 0; -int32 ptr_uc = 0; /* upper/lower case */ -int32 ptr_hold = 0; /* holding buffer */ -int32 ptr_leader = PTR_LEADER; /* leader count */ +int32 ptr_uc = 0; /* upper/lower case */ +int32 ptr_hold = 0; /* holding buffer */ +int32 ptr_leader = PTR_LEADER; /* leader count */ int32 ptp_stopioe = 0; -int32 tti_hold = 0; /* tti hold buf */ -int32 tty_buf = 0; /* tty buffer */ -int32 tty_uc = 0; /* tty uc/lc */ +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; @@ -89,139 +89,151 @@ t_stat ptp_reset (DEVICE *dptr); t_stat tty_reset (DEVICE *dptr); t_stat ptr_boot (int32 unitno, DEVICE *dptr); t_stat ptr_attach (UNIT *uptr, char *cptr); - + /* 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' }; + ' ', '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 }; - + 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 + 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 }; + UDATA (&ptr_svc, UNIT_SEQ+UNIT_ATTABLE+UNIT_ROABLE, 0), + SERIAL_IN_WAIT + }; REG ptr_reg[] = { - { ORDATA (BUF, ptr_unit.buf, 18) }, - { FLDATA (UC, ptr_uc, UC_V) }, - { FLDATA (DONE, iosta, IOS_V_PTR) }, - { FLDATA (RPLS, cpls, CPLS_V_PTR) }, - { ORDATA (HOLD, ptr_hold, 9), REG_HRO }, - { 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 }, - { DRDATA (LEADER, ptr_leader, 6), REG_HRO }, - { FLDATA (STOP_IOE, ptr_stopioe, 0) }, - { NULL } }; + { ORDATA (BUF, ptr_unit.buf, 18) }, + { FLDATA (UC, ptr_uc, UC_V) }, + { FLDATA (DONE, iosta, IOS_V_PTR) }, + { FLDATA (RPLS, cpls, CPLS_V_PTR) }, + { ORDATA (HOLD, ptr_hold, 9), REG_HRO }, + { 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 }, + { DRDATA (LEADER, ptr_leader, 6), REG_HRO }, + { FLDATA (STOP_IOE, ptr_stopioe, 0) }, + { NULL } + }; MTAB ptr_mod[] = { - { UNIT_ASCII, UNIT_ASCII, "ASCII", "ASCII", NULL }, - { UNIT_ASCII, 0, "FIODEC", "FIODEC", NULL }, - { 0 } }; + { UNIT_ASCII, UNIT_ASCII, "ASCII", "ASCII", NULL }, + { UNIT_ASCII, 0, "FIODEC", "FIODEC", NULL }, + { 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, NULL, - NULL, 0 }; + "PTR", &ptr_unit, ptr_reg, ptr_mod, + 1, 10, 31, 1, 8, 8, + NULL, NULL, &ptr_reset, + &ptr_boot, &ptr_attach, NULL, + NULL, 0 + }; /* PTP data structures - ptp_dev PTP device descriptor - ptp_unit PTP unit - ptp_reg PTP register list + 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 }; + 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 } }; + { 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 }; - + "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 + 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 * 10 } }; + { UDATA (&tti_svc, 0, 0), KBD_POLL_WAIT }, + { UDATA (&tto_svc, 0, 0), SERIAL_OUT_WAIT * 10 } + }; 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 } }; + { 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 }; - + "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, @@ -236,22 +248,25 @@ DEVICE tty_dev = { 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; } +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 */ +sim_activate (&ptr_unit, ptr_unit.wait); /* start reader */ return dat; } @@ -261,36 +276,43 @@ t_stat ptr_svc (UNIT *uptr) { int32 temp; -if ((uptr->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 ((uptr->flags & UNIT_ASCII) && (ptr_state == 0)) /* ASCII mode, alpha read? */ - temp = ptr_get_ascii (uptr); /* get processed char */ -else if ((temp = getc (uptr->fileref)) != EOF) /* no, get raw char */ - uptr->pos = uptr->pos + 1; /* if not eof, count */ -if (temp == EOF) { /* end of file? */ - if (ptr_wait) ptr_wait = ioh = 0; /* if wait, clr ioh */ - if (feof (uptr->fileref)) { - if ((cpls & CPLS_PTR) || ptr_stopioe) printf ("PTR end of file\n"); - else return SCPE_OK; } - else perror ("PTR I/O error"); - clearerr (uptr->fileref); - return SCPE_IOERR; } -if (ptr_state == 0) uptr->buf = temp & 0377; /* alpha */ -else if (temp & 0200) { /* binary */ - ptr_state = ptr_state - 6; - uptr->buf = uptr->buf | ((temp & 077) << ptr_state); } -if (ptr_state == 0) { /* done? */ - if (cpls & CPLS_PTR) { /* completion pulse? */ - iosta = iosta & ~IOS_PTR; /* clear flag */ - IO = uptr->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 (uptr, uptr->wait); /* get next char */ +if ((uptr->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 ((uptr->flags & UNIT_ASCII) && (ptr_state == 0)) /* ASCII mode, alpha read? */ + temp = ptr_get_ascii (uptr); /* get processed char */ +else if ((temp = getc (uptr->fileref)) != EOF) /* no, get raw char */ + uptr->pos = uptr->pos + 1; /* if not eof, count */ +if (temp == EOF) { /* end of file? */ + if (ptr_wait) ptr_wait = ioh = 0; /* if wait, clr ioh */ + if (feof (uptr->fileref)) { + if ((cpls & CPLS_PTR) || ptr_stopioe) printf ("PTR end of file\n"); + else return SCPE_OK; + } + else perror ("PTR I/O error"); + clearerr (uptr->fileref); + return SCPE_IOERR; + } +if (ptr_state == 0) uptr->buf = temp & 0377; /* alpha */ +else if (temp & 0200) { /* binary */ + ptr_state = ptr_state - 6; + uptr->buf = uptr->buf | ((temp & 077) << ptr_state); + } +if (ptr_state == 0) { /* done? */ + if (cpls & CPLS_PTR) { /* completion pulse? */ + iosta = iosta & ~IOS_PTR; /* clear flag */ + IO = uptr->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 (uptr, uptr->wait); /* get next char */ return SCPE_OK; } @@ -301,47 +323,52 @@ int ptr_get_ascii (UNIT *uptr) int c; int32 in; -if (ptr_leader > 0) { /* leader? */ - ptr_leader = ptr_leader - 1; /* count down */ - return 0; } -if (ptr_hold & CW) { /* char waiting? */ - in = ptr_hold & TT_WIDTH; /* return char */ - ptr_hold = 0; } /* not waiting */ -else { for (;;) { /* until valid char */ - if ((c = getc (uptr->fileref)) == EOF) /* get next char, EOF? */ - return FIODEC_STOP; /* return STOP */ - uptr->pos = uptr->pos + 1; /* count char */ - c = c & 0177; /* cut to 7b */ - if (c == '\n') c = '\r'; /* NL -> CR */ - else if (c == '\r') continue; /* ignore CR */ - in = ascii_to_fiodec[c]; /* convert char */ - if ((in == 0) && (c != ' ')) continue; /* ignore unknowns */ - if ((in & BOTH) || ((in & UC) == ptr_uc)) /* case match? */ - in = in & TT_WIDTH; /* cut to 6b */ - else { /* no, case shift */ - ptr_hold = in | CW; /* set char waiting */ - ptr_uc = in & UC; /* set case */ - in = ptr_uc? FIODEC_UC: FIODEC_LC; } /* return case */ - break; } - } /* end else */ -in = in * 010040201; /* even parity from */ -in = in | 027555555400; /* HACKMEM 167 */ +if (ptr_leader > 0) { /* leader? */ + ptr_leader = ptr_leader - 1; /* count down */ + return 0; + } +if (ptr_hold & CW) { /* char waiting? */ + in = ptr_hold & TT_WIDTH; /* return char */ + ptr_hold = 0; /* not waiting */ + } +else { + for (;;) { /* until valid char */ + if ((c = getc (uptr->fileref)) == EOF) /* get next char, EOF? */ + return FIODEC_STOP; /* return STOP */ + uptr->pos = uptr->pos + 1; /* count char */ + c = c & 0177; /* cut to 7b */ + if (c == '\n') c = '\r'; /* NL -> CR */ + else if (c == '\r') continue; /* ignore CR */ + in = ascii_to_fiodec[c]; /* convert char */ + if ((in == 0) && (c != ' ')) continue; /* ignore unknowns */ + if ((in & BOTH) || ((in & UC) == ptr_uc)) /* case match? */ + in = in & TT_WIDTH; /* cut to 6b */ + else { /* no, case shift */ + ptr_hold = in | CW; /* set char waiting */ + ptr_uc = in & UC; /* set case */ + in = ptr_uc? FIODEC_UC: FIODEC_LC; /* return case */ + } /* end else */ + break; + } /* end for */ + } /* end else */ +in = in * 010040201; /* even parity from */ +in = in | 027555555400; /* HACKMEM 167 */ in = in % (9 << 7); return in & 0377; } - + /* Reset routine */ t_stat ptr_reset (DEVICE *dptr) { -ptr_state = 0; /* clear state */ +ptr_state = 0; /* clear state */ ptr_wait = 0; ptr_hold = 0; ptr_uc = 0; ptr_unit.buf = 0; cpls = cpls & ~CPLS_PTR; -iosta = iosta & ~IOS_PTR; /* clear flag */ -sim_cancel (&ptr_unit); /* deactivate unit */ +iosta = iosta & ~IOS_PTR; /* clear flag */ +sim_cancel (&ptr_unit); /* deactivate unit */ return SCPE_OK; } @@ -349,7 +376,7 @@ return SCPE_OK; t_stat ptr_attach (UNIT *uptr, char *cptr) { -ptr_leader = PTR_LEADER; /* set up leader */ +ptr_leader = PTR_LEADER; /* set up leader */ return attach_unit (uptr, cptr); } @@ -360,11 +387,13 @@ 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++; } } + if ((tmp = getc (uptr->fileref)) == EOF) return -1; + uptr->pos = uptr->pos + 1; + if (tmp & 0200) { + word = (word << 6) | (tmp & 077); + i++; + } + } return word; } @@ -374,31 +403,34 @@ 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 */ + 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 */ +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; } +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 */ +sim_activate (&ptp_unit, ptp_unit.wait); /* start unit */ return dat; } @@ -406,17 +438,19 @@ return dat; 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 ((uptr->flags & UNIT_ATT) == 0) /* not attached? */ - return IORETURN (ptp_stopioe, SCPE_UNATT); -if (putc (uptr->buf, uptr->fileref) == EOF) { /* I/O error? */ - perror ("PTP I/O error"); - clearerr (uptr->fileref); - return SCPE_IOERR; } +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 ((uptr->flags & UNIT_ATT) == 0) /* not attached? */ + return IORETURN (ptp_stopioe, SCPE_UNATT); +if (putc (uptr->buf, uptr->fileref) == EOF) { /* I/O error? */ + perror ("PTP I/O error"); + clearerr (uptr->fileref); + return SCPE_IOERR; + } uptr->pos = uptr->pos + 1; return SCPE_OK; } @@ -425,32 +459,33 @@ return SCPE_OK; t_stat ptp_reset (DEVICE *dptr) { -ptp_unit.buf = 0; /* clear state */ +ptp_unit.buf = 0; /* clear state */ cpls = cpls & ~CPLS_PTP; -iosta = iosta & ~IOS_PTP; /* clear flag */ -sim_cancel (&ptp_unit); /* deactivate unit */ +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); +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; } +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 */ +sim_activate (&tty_unit[TTO], tty_unit[TTO].wait); /* activate unit */ return dat; } @@ -460,27 +495,31 @@ 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 */ +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; } @@ -490,21 +529,26 @@ t_stat tto_svc (UNIT *uptr) int32 c; t_stat r; -if (tty_buf == FIODEC_UC) tty_uc = UC; /* upper case? */ -else if (tty_buf == FIODEC_LC) tty_uc = 0; /* lower case? */ -else { c = fiodec_to_ascii[tty_buf | tty_uc]; /* translate */ - if (c && ((r = sim_putchar_s (c)) != SCPE_OK)) {/* output; error? */ - sim_activate (uptr, uptr->wait); /* retry */ - return ((r == SCPE_STALL)? SCPE_OK: r); } } -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) tty_uc = UC; /* upper case? */ +else if (tty_buf == FIODEC_LC) tty_uc = 0; /* lower case? */ +else { + c = fiodec_to_ascii[tty_buf | tty_uc]; /* translate */ + if (c && ((r = sim_putchar_s (c)) != SCPE_OK)) { /* output; error? */ + sim_activate (uptr, uptr->wait); /* retry */ + return ((r == SCPE_STALL)? SCPE_OK: r); + } + } +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 */ uptr->pos = uptr->pos + 1; -if (c == '\r') { /* cr? add lf */ - sim_putchar ('\n'); - uptr->pos = uptr->pos + 1; } +if (c == '\r') { /* cr? add lf */ + sim_putchar ('\n'); + uptr->pos = uptr->pos + 1; + } return SCPE_OK; } @@ -512,12 +556,12 @@ return SCPE_OK; t_stat tty_reset (DEVICE *dptr) { -tty_buf = 0; /* clear buffer */ -tty_uc = 0; /* clear case */ -tti_hold = 0; /* clear hold buf */ +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 */ +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 index 04418a96..5ea6c323 100644 --- a/PDP1/pdp1_sys.c +++ b/PDP1/pdp1_sys.c @@ -23,23 +23,23 @@ 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-Apr-04 RMS Fixed bug in binary loader (found by Mark Crispin) - 08-Feb-04 PLB Merged display support - 08-Dec-03 RMS Added parallel drum support, drum mnemonics - 18-Oct-03 RMS Added DECtape off reel message - 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) + 06-Apr-04 RMS Fixed bug in binary loader (found by Mark Crispin) + 08-Feb-04 PLB Merged display support + 08-Dec-03 RMS Added parallel drum support, drum mnemonics + 18-Oct-03 RMS Added DECtape off reel message + 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" @@ -64,12 +64,12 @@ 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 + 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"; @@ -79,27 +79,29 @@ 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, - &drp_dev, -// &dpy_dev, - NULL }; + &cpu_dev, + &ptr_dev, + &ptp_dev, + &tty_dev, + &lpt_dev, + &dt_dev, + &drm_dev, + &drp_dev, +/* &dpy_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", - "DECtape off reel" }; - + "Unknown error", + "Undefined instruction", + "HALT instruction", + "Breakpoint", + "Nested XCT's", + "Nested indirect addresses", + "Infinite I/O wait state", + "DECtape off reel" + }; + /* Binary loader - supports both RIM format and Macro block format */ int32 pdp1_getw (FILE *inf) @@ -108,10 +110,12 @@ 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++; } } + if ((tmp = getc (inf)) == EOF) return -1; + if (tmp & 0200) { + word = (word << 6) | (tmp & 077); + i++; + } + } return word; } @@ -120,18 +124,20 @@ t_stat rim_load (FILE *inf, int32 fld) int32 origin, val; for (;;) { - if ((val = pdp1_getw (inf)) < 0) return SCPE_FMT; - if (((val & 0760000) == OP_DIO) || /* DIO? */ - ((val & 0760000) == OP_DAC)) { /* hack - Macro1 err */ - origin = val & DAMASK; - if ((val = pdp1_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 */ + if ((val = pdp1_getw (inf)) < 0) return SCPE_FMT; + if (((val & 0760000) == OP_DIO) || /* DIO? */ + ((val & 0760000) == OP_DAC)) { /* hack - Macro1 err */ + origin = val & DAMASK; + if ((val = pdp1_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) @@ -139,30 +145,33 @@ t_stat blk_load (FILE *inf, int32 fld) int32 val, start, count, csum; for (;;) { - if ((val = pdp1_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 = pdp1_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 = pdp1_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 = pdp1_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 */ + if ((val = pdp1_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 = pdp1_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 = pdp1_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 = pdp1_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) @@ -172,52 +181,54 @@ int32 fld; if (flag != 0) return SCPE_ARG; if (cptr && (*cptr != 0)) { - fld = get_uint (cptr, 8, AMASK, &sta); - if (sta != SCPE_OK) return sta; - fld = fld & EPCMASK; } + 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 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 */ +#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 }; + 0770000, 0760017, 0760077, 0777000 + }; static const char *opcode[] = { - "AND", "IOR", "XOR", "XCT", /* mem refs */ + "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 */ + "CAL", "JDA", /* mem ref no ind */ - "IOH", "RPA", "RPB", "RRB", /* I/O instructions */ + "IOH", "RPA", "RPB", "RRB", /* I/O instructions */ "PPA", "PPB", "TYO", "TYI", "DPY", "LSM", "ESM", "CBS", @@ -230,12 +241,12 @@ static const char *opcode[] = { "SKP", "SKP I", "CLO", "SFT", "LAW", "OPR", - "RAL", "RIL", "RCL", /* shifts */ + "RAL", "RIL", "RCL", /* shifts */ "SAL", "SIL", "SCL", "RAR", "RIR", "RCR", "SAR", "SIR", "SCR", - "SZF1", "SZF2", "SZF3", /* skips */ + "SZF1", "SZF2", "SZF3", /* skips */ "SZF4", "SZF5", "SZF6", "SZF7", "SZS1", "SZS1 SZF1", "SZS1 SZF2", "SZS1 SZ3", "SZS1 SZF4", "SZS1 SZF5", "SZS1 SZF6", "SZS1 SZF7", @@ -252,17 +263,18 @@ static const char *opcode[] = { "SZS7", "SZS7 SZF1", "SZS7 SZF2", "SZS7 SZ3", "SZS7 SZF4", "SZS7 SZF5", "SZS7 SZF6", "SZS7 SZF7", - "CLF1", "CLF2", "CLF3", /* operates */ + "CLF1", "CLF2", "CLF3", /* operates */ "CLF4", "CLF5", "CLF6", "CLF7", "STF1", "STF2", "STF3", "STF4", "STF5", "STF6", "STF7", - "SZA", "SPA", "SMA", /* encode only */ + "SZA", "SPA", "SMA", /* encode only */ "SZO", "SPI", "I", "LAP", "CLA", "HLT", "CMA", "LAT", "CLI", - NULL, NULL, /* decode only */ - NULL }; + NULL, NULL, /* decode only */ + NULL + }; static const int32 opc_val[] = { 0020000+I_MRF, 0040000+I_MRF, 0060000+I_MRF, 0100000+I_MRF, @@ -313,48 +325,51 @@ static const int32 opc_val[] = { 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 */ + 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 }; - + 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? + *of = output stream + inst = mask bits + class = instruction class code + sp = space needed? Outputs: - status = space needed? + 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; } } +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 + *of = output stream + addr = current PC + *val = pointer to values + *uptr = pointer to unit + sw = switches Outputs: - return = status code + return = status code */ #define FMTASC(x) ((x) < 040)? "<%03o>": "%c", (x) @@ -362,99 +377,113 @@ return sp; #define ASCTOSIX(x) (ascii_to_fiodec[x] & 077) t_stat fprint_sym (FILE *of, t_addr addr, t_value *val, - UNIT *uptr, int32 sw) + 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 ('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? */ +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 */ + 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 + *cptr = pointer to input string + *sign = pointer to sign + *status = pointer to error status Outputs: - val = output value + val = output value */ t_value get_sint (char *cptr, int32 *sign, t_stat *status) { *sign = 1; if (*cptr == '+') { - *sign = 0; - cptr++; } + *sign = 0; + cptr++; + } else if (*cptr == '-') { - *sign = -1; - 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 + *cptr = pointer to input string + addr = current PC + uptr = pointer to unit + *val = pointer to output values + sw = switches Outputs: - status = error status + status = error status */ t_stat parse_sym (char *cptr, t_addr addr, UNIT *uptr, t_value *val, int32 sw) @@ -467,64 +496,72 @@ 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 (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 (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 */ + 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; + } -cptr = get_glyph (cptr, gbuf, 0); /* get opcode */ +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 */ +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? */ +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 index 8d6460ec..2a64d9dc 100644 --- a/PDP10/pdp10_cpu.c +++ b/PDP10/pdp10_cpu.c @@ -1,6 +1,6 @@ /* pdp10_cpu.c: PDP-10 CPU simulator - Copyright (c) 1993-2004, Robert M. Supnik + Copyright (c) 1993-2005, 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"), @@ -19,65 +19,65 @@ 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 + 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 + cpu KS10 central processor - 10-Nov-04 RMS Added instruction history - 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 + 16-Aug-05 RMS Fixed C++ declaration and cast problems + 10-Nov-04 RMS Added instruction history + 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 + 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 - +---------+----+-+----+------------------+ + 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. + + 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. @@ -86,15 +86,15 @@ 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 + 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, @@ -116,8 +116,8 @@ 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 + 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 @@ -127,76 +127,78 @@ 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) +#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) -#define HIST_PC 0x40000000 -#define HIST_MIN 64 -#define HIST_MAX 65536 -struct InstHistory { - a10 pc; - a10 ea; - d10 ir; - d10 ac; }; +#define HIST_PC 0x40000000 +#define HIST_MIN 64 +#define HIST_MAX 65536 -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 */ +typedef struct { + a10 pc; + a10 ea; + d10 ir; + d10 ac; + } InstHistory; + +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 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 */ +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; -int32 hst_p = 0; /* history pointer */ -int32 hst_lnt = 0; /* history length */ -struct InstHistory *hst = NULL; /* instruction history */ +int32 hst_p = 0; /* history pointer */ +int32 hst_lnt = 0; /* history length */ +InstHistory *hst = NULL; /* 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 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); @@ -243,14 +245,14 @@ 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 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 (); @@ -317,93 +319,97 @@ 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 + 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 } }; + { 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 }, - { MTAB_XTD|MTAB_VDV|MTAB_NMO|MTAB_SHP, 0, "HISTORY", "HISTORY", - &cpu_set_hist, &cpu_show_hist }, - { 0 } }; + { 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 }, + { MTAB_XTD|MTAB_VDV|MTAB_NMO|MTAB_SHP, 0, "HISTORY", "HISTORY", + &cpu_set_hist, &cpu_show_hist }, + { 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 }; - + "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 }; + 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, @@ -413,7 +419,8 @@ const int32 pi_m2lvl[128] = { 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 + }; const d10 bytemask[64] = { 0, 01, 03, 07, 017, 037, 077, @@ -428,192 +435,199 @@ const d10 bytemask[64] = { 0, 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 }; + 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 }; + &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 }; + 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 }; + &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 }; + &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 }; + &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 */ - +#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 }; - + 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) +#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 +#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) +#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)) +#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) +#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)) +#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]); } - +#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 */ +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 */ +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 @@ -621,59 +635,65 @@ if (!ITS) its_1pr = 0; /* ~ITS, clr 1-proc */ 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 */ +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 */ - +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 */ +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 */ +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. @@ -682,39 +702,44 @@ if (sim_interval <= 0) { /* check clock queue */ */ 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 */ - + 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, @@ -725,55 +750,61 @@ if (qintr) { */ 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 */ + 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 */ +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; } + inst = Read (pager_PC = PC, MM_CUR); /* get instruction */ + INCPC; + sim_interval = sim_interval - 1; + } -its_2pr = its_1pr; /* save 1-proc flag */ +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; } +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 */ -if (hst_lnt) { /* history enabled? */ - hst_p = (hst_p + 1); /* next entry */ - if (hst_p >= hst_lnt) hst_p = 0; - hst[hst_p].pc = pager_PC | HIST_PC; - hst[hst_p].ea = ea; - hst[hst_p].ir = inst; - hst[hst_p].ac = AC(ac); } -switch (op) { /* case on opcode */ - + ABORT (STOP_IND); /* too many ind? stop */ +if (hst_lnt) { /* history enabled? */ + hst_p = (hst_p + 1); /* next entry */ + if (hst_p >= hst_lnt) hst_p = 0; + hst[hst_p].pc = pager_PC | HIST_PC; + hst[hst_p].ea = ea; + hst[hst_p].ir = inst; + hst[hst_p].ac = AC(ac); + } +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 0000: if (stop_op0) { ABORT (STOP_ILLEG); } + goto MUUO; +case 0001: /* local UUO's */ case 0002: case 0003: case 0004: @@ -803,91 +834,98 @@ 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 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 */ - +/* 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; /* clear log */ + switch (st) { + 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 @@ -896,357 +934,360 @@ case 0177: RM; if (FDVR (mb)) { S1AC; WRAC; } break; /* FDVRB */ 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 */ - +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 */ - +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 */ - +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 */ - +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 */ - +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; @@ -1256,25 +1297,25 @@ case 0677: TS_; T__N; T_O; break; /* TSON */ 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 */ +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. @@ -1285,124 +1326,140 @@ case 0725: IOA; io725 (AC(ac), ea); break; /* BCIOB, IOWRBQ */ */ 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; - +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 + - (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 */ +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 */ -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 */ + 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 + 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) @@ -1410,14 +1467,16 @@ 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 */ +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; } @@ -1428,14 +1487,16 @@ 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 */ +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; } @@ -1461,7 +1522,7 @@ 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 */ @@ -1471,14 +1532,16 @@ 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(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; @@ -1491,14 +1554,16 @@ 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(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; @@ -1514,18 +1579,25 @@ 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; } } + 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; } @@ -1540,13 +1612,16 @@ 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; } + 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) @@ -1557,10 +1632,10 @@ d10 fill = sign? ONES: 0; d10 so; if (sc == 0) return val; -if (sc > 35) sc = 35; /* cap sc at 35 */ +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 */ + 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)); } @@ -1574,32 +1649,39 @@ 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 */ +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); } } + 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 @@ -1613,11 +1695,12 @@ 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; } + 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; } @@ -1627,7 +1710,7 @@ return ea; - 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) + entire word fetch (single level) */ a10 calc_ioea (d10 inst, int32 pflgs) @@ -1637,12 +1720,14 @@ 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; } +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; } @@ -1656,15 +1741,16 @@ 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; } + 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 */ @@ -1674,15 +1760,16 @@ 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 */ +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 */ +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; } @@ -1694,13 +1781,13 @@ a10 ba; int32 p, s; d10 bp, wd; -bp = Read (ea, MM_OPND); /* get byte ptr */ -p = GET_P (bp); /* get P and S */ +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 */ +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; } @@ -1712,14 +1799,14 @@ 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 */ +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 */ +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 */ +wd = (wd & ~mask) | (val & mask); /* insert byte */ Write (ba, wd & DMASK, MM_BSTK); return; } @@ -1734,28 +1821,31 @@ 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 */ +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; + 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, @@ -1772,30 +1862,34 @@ 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; } +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 */ +#define BYTE1 0776000000000 +#define BYTE2 0001774000000 +#define BYTE3 0000003770000 +#define BYTE4 0000000007760 +/* unused 0000000000017 */ void bltu (int32 ac, a10 ea, int32 pflgs, int dir) { @@ -1806,24 +1900,28 @@ 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; } +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; } @@ -1833,14 +1931,13 @@ 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 */ +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 @@ -1872,10 +1969,11 @@ 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 */ +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 @@ -1891,26 +1989,27 @@ 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 */ +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 + 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) @@ -1926,14 +2025,15 @@ 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 */ +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; } @@ -1962,37 +2062,39 @@ 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 */ +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 + (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 + 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 + 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 */ @@ -2002,13 +2104,13 @@ 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 */ +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; } @@ -2045,37 +2147,38 @@ 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; } + 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 */ +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 */ +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) M = (d10 *) calloc (MAXMEMSIZE, sizeof (d10)); if (M == NULL) return SCPE_MEM; pcq_r = find_reg ("PCQ", NULL, dptr); if (pcq_r) pcq_r->qptr = 0; @@ -2090,11 +2193,14 @@ 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; } +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; } @@ -2103,11 +2209,14 @@ return SCPE_OK; 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; } +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; } @@ -2133,20 +2242,23 @@ int32 i, lnt; t_stat r; if (cptr == NULL) { - for (i = 0; i < hst_lnt; i++) hst[i].pc = 0; - hst_p = 0; - return SCPE_OK; } + for (i = 0; i < hst_lnt; i++) hst[i].pc = 0; + hst_p = 0; + return SCPE_OK; + } lnt = (int32) get_uint (cptr, 10, HIST_MAX, &r); if ((r != SCPE_OK) || (lnt && (lnt < HIST_MIN))) return SCPE_ARG; hst_p = 0; if (hst_lnt) { - free (hst); - hst_lnt = 0; - hst = NULL; } + free (hst); + hst_lnt = 0; + hst = NULL; + } if (lnt) { - hst = calloc (sizeof (struct InstHistory), lnt); - if (hst == NULL) return SCPE_MEM; - hst_lnt = lnt; } + hst = (InstHistory *) calloc (lnt, sizeof (InstHistory)); + if (hst == NULL) return SCPE_MEM; + hst_lnt = lnt; + } return SCPE_OK; } @@ -2158,29 +2270,30 @@ int32 k, di, lnt; char *cptr = (char *) desc; t_stat r; t_value sim_eval; -struct InstHistory *h; +InstHistory *h; extern t_stat fprint_sym (FILE *ofile, t_addr addr, t_value *val, - UNIT *uptr, int32 sw); + UNIT *uptr, int32 sw); -if (hst_lnt == 0) return SCPE_NOFNC; /* enabled? */ +if (hst_lnt == 0) return SCPE_NOFNC; /* enabled? */ if (cptr) { - lnt = (int32) get_uint (cptr, 10, hst_lnt, &r); - if ((r != SCPE_OK) || (lnt == 0)) return SCPE_ARG; } + lnt = (int32) get_uint (cptr, 10, hst_lnt, &r); + if ((r != SCPE_OK) || (lnt == 0)) return SCPE_ARG; + } else lnt = hst_lnt; -di = hst_p - lnt; /* work forward */ +di = hst_p - lnt; /* work forward */ if (di < 0) di = di + hst_lnt; fprintf (st, "PC AC EA IR\n\n"); -for (k = 0; k < lnt; k++) { /* print specified */ - h = &hst[(++di) % hst_lnt]; /* entry pointer */ - if (h->pc & HIST_PC) { /* instruction? */ - fprintf (st, "%06o ", h->pc & AMASK); - fprintf (st, "%012o ", h->ac); - fprintf (st, "%06o ", h->ea); - sim_eval = h->ir; - if ((fprint_sym (st, h->pc & AMASK, &sim_eval, &cpu_unit, SWMASK ('M'))) > 0) - fprintf (st, "(undefined) %012o", h->ir); - fputc ('\n', st); /* end line */ - } /* end else instruction */ - } /* end for */ +for (k = 0; k < lnt; k++) { /* print specified */ + h = &hst[(++di) % hst_lnt]; /* entry pointer */ + if (h->pc & HIST_PC) { /* instruction? */ + fprintf (st, "%06o ", h->pc & AMASK); + fprintf (st, "%012o ", h->ac); + fprintf (st, "%06o ", h->ea); + sim_eval = h->ir; + if ((fprint_sym (st, h->pc & AMASK, &sim_eval, &cpu_unit, SWMASK ('M'))) > 0) + fprintf (st, "(undefined) %012o", h->ir); + fputc ('\n', st); /* end line */ + } /* end else instruction */ + } /* end for */ return SCPE_OK; } diff --git a/PDP10/pdp10_defs.h b/PDP10/pdp10_defs.h index b8ddc1b1..62d4df48 100644 --- a/PDP10/pdp10_defs.h +++ b/PDP10/pdp10_defs.h @@ -1,6 +1,6 @@ /* pdp10_defs.h: PDP-10 simulator definitions - Copyright (c) 1993-2004, Robert M Supnik + Copyright (c) 1993-2005, 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"), @@ -19,53 +19,53 @@ 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 + 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. - 29-Dec-03 RMS Added Q18 definition for PDP11 compatibility - 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 + 29-Dec-03 RMS Added Q18 definition for PDP11 compatibility + 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 +#define _PDP10_DEFS_H_ 0 -#ifndef VM_PDP10 -#define VM_PDP10 0 +#ifndef VM_PDP10 +#define VM_PDP10 0 #endif -#include "sim_defs.h" /* simulator defns */ +#include "sim_defs.h" /* simulator defns */ /* Digital Equipment Corporation's 36b family had six implementations: - name mips comments + 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 + 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 + 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 + 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 @@ -87,8 +87,8 @@ /* Data types */ -typedef int32 a10; /* PDP-10 addr (30b) */ -typedef t_int64 d10; /* PDP-10 data (36b) */ +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 @@ -96,295 +96,295 @@ typedef t_int64 d10; /* PDP-10 data (36b) */ 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 */ +#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 */ +#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) +#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 +#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)) +#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)) +#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) +#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 +#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) +#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)) +#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 +#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)) +#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 */ +#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 */ +#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) +#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) +#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 */ +#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 */ +#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) +#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) +#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 @@ -395,17 +395,17 @@ typedef t_int64 d10; /* PDP-10 data (36b) */ 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) +#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. @@ -413,326 +413,326 @@ typedef t_int64 d10; /* PDP-10 data (36b) */ 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) +#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 */ +#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 */ +#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 */ +#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 */ +#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)) +#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)) +#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]))) +#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) +#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) +#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)) +#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) +#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 */ +#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 */ + 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 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_Q18 (DEV_V_UF + 2) /* Qbus, mem <= 256KB */ -#define DEV_V_FLTA (DEV_V_UF + 3) /* float addr */ -#define DEV_UBUS (1u << DEV_V_UBUS) -#define DEV_QBUS (1u << DEV_V_QBUS) -#define DEV_Q18 (1u << DEV_V_Q18) -#define DEV_FLTA (1u << DEV_V_FLTA) +#define DEV_V_UBUS (DEV_V_UF + 0) /* Unibus */ +#define DEV_V_QBUS (DEV_V_UF + 1) /* Qbus */ +#define DEV_V_Q18 (DEV_V_UF + 2) /* Qbus, mem <= 256KB */ +#define DEV_V_FLTA (DEV_V_UF + 3) /* float addr */ +#define DEV_UBUS (1u << DEV_V_UBUS) +#define DEV_QBUS (1u << DEV_V_QBUS) +#define DEV_Q18 (1u << DEV_V_Q18) +#define DEV_FLTA (1u << DEV_V_FLTA) -#define UNIBUS TRUE /* 18b only */ +#define UNIBUS TRUE /* 18b only */ -#define DEV_RDX 8 /* default device radix */ +#define DEV_RDX 8 /* default device radix */ /* I/O page layout */ -#define IOPAGEBASE 0760000 /* I/O page base */ -#define IOBA_UBMAP 0763000 +#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_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 +#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) +#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 + <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_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 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 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_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 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 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) +#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 */ @@ -746,6 +746,6 @@ t_stat set_addr_flt (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); +t_stat auto_config (char *name, int32 num); #endif diff --git a/PDP10/pdp10_doc.txt b/PDP10/pdp10_doc.txt index 79d1776e..7b2e9ddb 100644 --- a/PDP10/pdp10_doc.txt +++ b/PDP10/pdp10_doc.txt @@ -1,14 +1,14 @@ To: Users From: Bob Supnik Subj: PDP-10 Simulator Usage -Date: 15-Nov-2004 +Date: 01-Jul-2005 COPYRIGHT NOTICE The following copyright notice applies to both the SIMH source and binary: - Original code published in 1993-2004, written by Robert M Supnik - Copyright (c) 1993-2004, Robert M Supnik + Original code published in 1993-2005, written by Robert M Supnik + Copyright (c) 1993-2005, 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"), @@ -27,8 +27,8 @@ The following copyright notice applies to both the SIMH source and binary: 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 + 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. @@ -383,7 +383,7 @@ 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 SET DZ DISCONNECT=linenumber command disconnects the specified line. The DZ11 implements these registers: diff --git a/PDP10/pdp10_fe.c b/PDP10/pdp10_fe.c index c3c5066f..9fc91794 100644 --- a/PDP10/pdp10_fe.c +++ b/PDP10/pdp10_fe.c @@ -19,24 +19,24 @@ 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 + 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 + fe KS10 console front end - 28-May-04 RMS Removed SET FE CTRL-C - 29-Dec-03 RMS Added console backpressure support - 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 + 28-May-04 RMS Removed SET FE CTRL-C + 29-Dec-03 RMS Added console backpressure support + 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) +#define UNIT_DUMMY (1 << UNIT_V_UF) extern d10 *M; extern int32 apr_flg; @@ -47,37 +47,41 @@ t_stat fe_stop_os (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 + 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] +#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 } }; + { 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 } }; + { 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 }, - { 0 } }; + { UNIT_DUMMY, 0, NULL, "STOP", &fe_stop_os }, + { 0 } + }; DEVICE fe_dev = { - "FE", fe_unit, fe_reg, fe_mod, - 2, 10, 31, 1, 8, 8, - NULL, NULL, &fe_reset, - NULL, NULL, NULL }; - + "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 @@ -106,13 +110,15 @@ DEVICE fe_dev = { void fe_intr (void) { -if (M[FE_CTYOUT] & FE_CVALID) { /* char to print? */ - feo_unit.buf = (int32) M[FE_CTYOUT] & 0177; /* pick it up */ - feo_unit.pos = feo_unit.pos + 1; - sim_activate (&feo_unit, feo_unit.wait); } /* 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 */ +if (M[FE_CTYOUT] & FE_CVALID) { /* char to print? */ + feo_unit.buf = (int32) M[FE_CTYOUT] & 0177; /* pick it up */ + feo_unit.pos = feo_unit.pos + 1; + sim_activate (&feo_unit, feo_unit.wait); /* 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; } @@ -120,11 +126,12 @@ t_stat feo_svc (UNIT *uptr) { t_stat r; -if ((r = sim_putchar_s (uptr->buf)) != SCPE_OK) { /* output; error? */ - sim_activate (uptr, uptr->wait); /* try again */ - return ((r == SCPE_STALL)? SCPE_OK: r); } /* !stall? report */ -M[FE_CTYOUT] = 0; /* clear char */ -apr_flg = apr_flg | APRF_CON; /* interrupt KS10 */ +if ((r = sim_putchar_s (uptr->buf)) != SCPE_OK) { /* output; error? */ + sim_activate (uptr, uptr->wait); /* try again */ + return ((r == SCPE_STALL)? SCPE_OK: r); /* !stall? report */ + } +M[FE_CTYOUT] = 0; /* clear char */ +apr_flg = apr_flg | APRF_CON; /* interrupt KS10 */ return SCPE_OK; } @@ -132,16 +139,16 @@ 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 */ +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 */ +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) @@ -149,7 +156,7 @@ 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 */ +sim_activate (&fei_unit, fei_unit.wait); /* start input poll */ return SCPE_OK; } @@ -157,6 +164,6 @@ return SCPE_OK; t_stat fe_stop_os (UNIT *uptr, int32 val, char *cptr, void *desc) { -M[FE_SWITCH] = IOBA_RP; /* tell OS to stop */ +M[FE_SWITCH] = IOBA_RP; /* tell OS to stop */ return SCPE_OK; } diff --git a/PDP10/pdp10_ksio.c b/PDP10/pdp10_ksio.c index a494b1af..5e2532f4 100644 --- a/PDP10/pdp10_ksio.c +++ b/PDP10/pdp10_ksio.c @@ -1,6 +1,6 @@ /* pdp10_ksio.c: PDP-10 KS10 I/O subsystem simulator - Copyright (c) 1993-2004, Robert M Supnik + Copyright (c) 1993-2005, 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"), @@ -19,25 +19,25 @@ 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 + 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 + uba Unibus adapters - 25-Jan-04 RMS Added stub floating address routine - 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 + 25-Jan-04 RMS Added stub floating address routine + 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 @@ -67,39 +67,42 @@ 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 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) + 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 */ +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 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) }; + 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) }; + 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 *M; /* main memory */ extern d10 *ac_cur; extern d10 pager_word; extern int32 flags, pi_l2bit[8]; @@ -127,12 +130,12 @@ 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 + 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 }; @@ -144,93 +147,99 @@ 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) } }; + { 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 } }; + { 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 }; + "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 */ +DIB *dib_tab[DIB_MAX]; /* run-time DIBs */ -int32 (*int_ack[32])(void); /* int ack routines */ +int32 (*int_ack[32])(void); /* int ack routines */ -int32 int_vec[32]; /* int vectors */ +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 +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; } +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 +/* 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; } +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] +/* 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 */ +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] +/* 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 */ +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 +/* IO 714 (DEC) BSIO - set bit in I/O address + (ITS) IOWRI - write word to Unibus 3 */ void io714 (d10 val, a10 ea) @@ -238,16 +247,17 @@ void io714 (d10 val, a10 ea) d10 temp; val = val & 0177777; -if (ITS) WriteIO (IO_UBA3 | ea, val, WRITE); /* IOWRI */ +if (ITS) WriteIO (IO_UBA3 | ea, val, WRITE); /* IOWRI */ else { - temp = ReadIO (ea); /* BSIO */ - temp = temp | val; - WriteIO (ea, temp, WRITE); } + 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 +/* IO 715 (DEC) BCIO - clear bit in I/O address + (ITS) IOWRQ - write word to Unibus 1 */ void io715 (d10 val, a10 ea) @@ -255,76 +265,81 @@ void io715 (d10 val, a10 ea) d10 temp; val = val & 0177777; -if (ITS) WriteIO (IO_UBA1 | ea, val, WRITE); /* IOWRQ */ +if (ITS) WriteIO (IO_UBA1 | ea, val, WRITE); /* IOWRQ */ else { - temp = ReadIO (ea); /* BCIO */ - temp = temp & ~val; - WriteIO (ea, temp, WRITE); } + 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 +/* 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; } +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 +/* 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; } +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] +/* 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 */ +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] +/* 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 */ +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 +/* IO 724 (DEC) BSIOB - set bit in I/O byte address + (ITS) IOWRBI - write byte to Unibus 3 */ void io724 (d10 val, a10 ea) @@ -332,17 +347,18 @@ void io724 (d10 val, a10 ea) d10 temp; val = val & 0377; -if (ITS) WriteIO (IO_UBA3 | ea, val, WRITEB); /* IOWRBI */ +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); } + 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 +/* IO 725 (DEC) BCIOB - clear bit in I/O byte address + (ITS) IOWRBQ - write byte to Unibus 1 */ void io725 (d10 val, a10 ea) @@ -350,15 +366,16 @@ void io725 (d10 val, a10 ea) d10 temp; val = val & 0377; -if (ITS) WriteIO (IO_UBA1 | ea, val, WRITEB); /* IOWRBQ */ +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); } + 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. @@ -371,11 +388,13 @@ 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); } } + if ((pa >= dibp->ba) && + (pa < (dibp->ba + dibp->lnt))) { + dibp->rd (&val, pa, READ); + pi_eval (); + return ((d10) val); + } + } UBNXM_FAIL (pa, READ); } @@ -386,23 +405,25 @@ 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; } } + 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 standard Unibus devices on Unibus 1 */ a10 Map_Addr10 (a10 ba, int32 ub) { a10 pa10; -int32 vpn = PAG_GETVPN (ba >> 2); /* get PDP-10 page number */ - +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? */ + ((ubmap[ub][vpn] & UMAP_VLD) == 0)) return -1; /* invalid map? */ pa10 = (ubmap[ub][vpn] + PAG_GETOFF (ba >> 2)) & PAMASK; return pa10; } @@ -413,13 +434,14 @@ uint32 lim; a10 pa10; lim = ba + bc; -for ( ; ba < lim; ba++) { /* by bytes */ - pa10 = Map_Addr10 (ba, 1); /* map addr */ - if ((pa10 < 0) || MEM_ADDR_NXM (pa10)) { /* inv map or NXM? */ - ubcs[1] = ubcs[1] | UBCS_TMO; /* UBA times out */ - return (lim - ba); } /* return bc */ - *buf++ = (uint8) ((M[pa10] >> ubashf[ba & 3]) & 0377); - } +for ( ; ba < lim; ba++) { /* by bytes */ + pa10 = Map_Addr10 (ba, 1); /* map addr */ + if ((pa10 < 0) || MEM_ADDR_NXM (pa10)) { /* inv map or NXM? */ + ubcs[1] = ubcs[1] | UBCS_TMO; /* UBA times out */ + return (lim - ba); /* return bc */ + } + *buf++ = (uint8) ((M[pa10] >> ubashf[ba & 3]) & 0377); + } return 0; } @@ -428,15 +450,16 @@ int32 Map_ReadW (uint32 ba, int32 bc, uint16 *buf) uint32 lim; a10 pa10; -ba = ba & ~01; /* align start */ +ba = ba & ~01; /* align start */ lim = ba + (bc & ~01); -for ( ; ba < lim; ba = ba + 2) { /* by words */ - pa10 = Map_Addr10 (ba, 1); /* map addr */ - if ((pa10 < 0) || MEM_ADDR_NXM (pa10)) { /* inv map or NXM? */ - ubcs[1] = ubcs[1] | UBCS_TMO; /* UBA times out */ - return (lim - ba); } /* return bc */ - *buf++ = (uint16) ((M[pa10] >> ((ba & 2)? 0: 18)) & 0177777); - } +for ( ; ba < lim; ba = ba + 2) { /* by words */ + pa10 = Map_Addr10 (ba, 1); /* map addr */ + if ((pa10 < 0) || MEM_ADDR_NXM (pa10)) { /* inv map or NXM? */ + ubcs[1] = ubcs[1] | UBCS_TMO; /* UBA times out */ + return (lim - ba); /* return bc */ + } + *buf++ = (uint16) ((M[pa10] >> ((ba & 2)? 0: 18)) & 0177777); + } return 0; } @@ -444,16 +467,19 @@ int32 Map_WriteB (uint32 ba, int32 bc, uint8 *buf) { uint32 lim; a10 pa10; -static d10 mask = 0377; +d10 mask; lim = ba + bc; -for ( ; ba < lim; ba++) { /* by bytes */ - pa10 = Map_Addr10 (ba, 1); /* map addr */ - if ((pa10 < 0) || MEM_ADDR_NXM (pa10)) { /* inv map or NXM? */ - ubcs[1] = ubcs[1] | UBCS_TMO; /* UBA times out */ - return (lim - ba); } /* return bc */ - M[pa10] = (M[pa10] & ~(mask << ubashf[ba & 3])) | - (((d10) *buf++) << ubashf[ba & 3]); } +for ( ; ba < lim; ba++) { /* by bytes */ + pa10 = Map_Addr10 (ba, 1); /* map addr */ + if ((pa10 < 0) || MEM_ADDR_NXM (pa10)) { /* inv map or NXM? */ + ubcs[1] = ubcs[1] | UBCS_TMO; /* UBA times out */ + return (lim - ba); /* return bc */ + } + mask = 0377; + M[pa10] = (M[pa10] & ~(mask << ubashf[ba & 3])) | + (((d10) *buf++) << ubashf[ba & 3]); + } return 0; } @@ -463,20 +489,21 @@ uint32 lim; a10 pa10; d10 val; -ba = ba & ~01; /* align start */ +ba = ba & ~01; /* align start */ lim = ba + (bc & ~01); -for ( ; ba < lim; ba++) { /* by bytes */ - pa10 = Map_Addr10 (ba, 1); /* map addr */ - if ((pa10 < 0) || MEM_ADDR_NXM (pa10)) { /* inv map or NXM? */ - ubcs[1] = ubcs[1] | 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); - } +for ( ; ba < lim; ba++) { /* by bytes */ + pa10 = Map_Addr10 (ba, 1); /* map addr */ + if ((pa10 < 0) || MEM_ADDR_NXM (pa10)) { /* inv map or NXM? */ + ubcs[1] = ubcs[1] | 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 () @@ -484,10 +511,11 @@ 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])]; } + 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; } @@ -495,7 +523,7 @@ return lvl; 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 + otherwise, returns 0 */ int32 pi_ub_vec (int32 rlvl, int32 *uba) @@ -503,19 +531,22 @@ 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 */ + 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) @@ -555,8 +586,9 @@ 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; } + 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; @@ -575,7 +607,9 @@ t_stat wr_nop (int32 val, int32 pa, int32 mode) { return SCPE_OK; } - + +/* Simulator interface routines */ + t_stat uba_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw) { int32 uba = uptr - uba_unit; @@ -600,12 +634,13 @@ 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; } + 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) @@ -621,12 +656,12 @@ 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 */ +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 (newba % ((uint32) val)) return SCPE_ARG; /* check modulus */ if (GET_IOUBA (newba) != GET_IOUBA (dibp->ba)) return SCPE_ARG; -dibp->ba = newba; /* store */ +dibp->ba = newba; /* store */ return SCPE_OK; } @@ -644,7 +679,7 @@ 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); + fprintf (st, "-%07o", dibp->ba + dibp->lnt - 1); return SCPE_OK; } @@ -688,11 +723,13 @@ 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))); } +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) @@ -701,21 +738,23 @@ 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; } } +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; } @@ -736,27 +775,31 @@ 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 */ +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; } @@ -768,31 +811,35 @@ 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"); - } +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) +t_stat auto_config (char *name, int32 num) { return SCPE_OK; } diff --git a/PDP10/pdp10_lp20.c b/PDP10/pdp10_lp20.c index 155a4fe8..d29fe336 100644 --- a/PDP10/pdp10_lp20.c +++ b/PDP10/pdp10_lp20.c @@ -19,145 +19,144 @@ 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 + 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 + lp20 line printer - 18-Mar-05 RMS Added attached test to detach routine - 29-Dec-03 RMS Fixed bug in scheduling - 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 + 04-Sep-05 RMS Fixed missing return (found by Peter Schorn) + 07-Jul-05 RMS Removed extraneous externs + 18-Mar-05 RMS Added attached test to detach routine + 29-Dec-03 RMS Fixed bug in scheduling + 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 */ +#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 */ +#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) +#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) +#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) +#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 */ +#define BC_MASK 0007777 /* <15:12> MBZ */ /* LPPAGC (765510) */ -#define PAGC_MASK 0007777 /* <15:12> MBZ */ +#define PAGC_MASK 0007777 /* <15:12> MBZ */ /* LPRDAT (765512) */ -#define RDAT_MASK 0007777 /* <15:12> MBZ */ +#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 */ +extern d10 *M; /* main memory */ +extern int32 int_req; + +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); @@ -175,285 +174,332 @@ void update_lpcs (int32 flg); /* LP data structures - lp20_dev LPT device descriptor - lp20_unit LPT unit descriptor - lp20_reg LPT register list + 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 } }; +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 }; + 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 } }; + { 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 } }; + { 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 }; - + "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 + 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 */ +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.wait); } } - 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); /* 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.wait); + } + } + 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 */ + } /* end case PA */ + 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 + 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; } + 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; +int32 dvld = -2; /* must be even */ 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 }; + 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); } + update_lpcs (CSA_ERR); + return IORETURN (lp20_stopioe, SCPE_UNATT); + } if ((fnc == FNC_PR) && (dvlnt == 0)) { - update_lpcs (CSA_ERR); - return SCPE_OK; } + update_lpcs (CSA_ERR); + return SCPE_OK; + } for (i = 0, cont = TRUE; (i < tbc) && cont; ba++, i++) { - if (Map_ReadW (ba, 2, &wd10)) { /* 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 */ + if (Map_ReadW (ba, 2, &wd10)) { /* 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; + 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; + 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 */ + 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 (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; } + 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 + 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 */ @@ -463,20 +509,24 @@ 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 */ +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; @@ -488,17 +538,20 @@ t_bool lp20_adv (int32 cnt, t_bool dvuadv) int32 i; if (cnt == 0) return TRUE; -lpcolc = 0; /* reset col cntr */ +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; } } +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; } @@ -506,40 +559,45 @@ 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 */ +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 */ +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; } + lpcsa = lpcsa | CSA_ONL; + lpcsb = lpcsb & ~CSB_OFFL; + } else lpcsa = lpcsa & ~CSA_DONE; if (dvlnt) { - lpcsa = lpcsa | CSA_DVON; - lpcsb = lpcsb & ~CSB_DVOF; } + 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; @@ -550,31 +608,31 @@ return; int32 lp20_inta (void) { -lp20_irq = 0; /* clear int req */ +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 */ +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 */ +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 */ + +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; } @@ -582,7 +640,7 @@ t_stat lp20_detach (UNIT *uptr) { t_stat reason; -if (!(uptr->flags & UNIT_ATT)) return SCPE_OK; /* attached? */ +if (!(uptr->flags & UNIT_ATT)) return SCPE_OK; /* attached? */ reason = detach_unit (uptr); sim_cancel (&lp20_unit); lpcsa = lpcsa & ~CSA_GO; diff --git a/PDP10/pdp10_mdfp.c b/PDP10/pdp10_mdfp.c index 0b753705..348c990a 100644 --- a/PDP10/pdp10_mdfp.c +++ b/PDP10/pdp10_mdfp.c @@ -1,6 +1,6 @@ /* pdp10_mdfp.c: PDP-10 multiply/divide and floating point simulator - Copyright (c) 1993-2004, Robert M Supnik + Copyright (c) 1993-2005, 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"), @@ -19,31 +19,33 @@ 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 + 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. - 2-Apr-04 RMS Fixed bug in floating point unpack - Fixed bug in FIXR (found by Phil Stone, fixed by - Chris Smith) + 2-Apr-04 RMS Fixed bug in floating point unpack + Fixed bug in FIXR (found by Phil Stone, fixed by + Chris Smith) + 31-Aug-01 RMS Changed int64 to t_int64 for Windoze + 10-Aug-01 RMS Removed register in declarations 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 + 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 @@ -94,87 +96,85 @@ 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 { /* unpacked fp number */ + int32 sign; /* sign */ + int32 exp; /* exponent */ + t_uint64 fhi; /* fraction high */ + t_uint64 flo; /* for double prec */ + } UFP; -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 */ +#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) +#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 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) +#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 */ +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 */ +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]; } @@ -185,16 +185,17 @@ return rs[1]; t_bool idiv (d10 a, d10 b, d10 *rs) { -d10 dvd = ABS (a); /* make ops positive */ +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 */ +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; } @@ -206,25 +207,30 @@ 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 ((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 - */ +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; } @@ -236,31 +242,37 @@ return; t_bool divi (int32 ac, d10 b, d10 *rs) { int32 p1 = ADDAC (ac, 1); -d10 dvr = ABS (b); /* make divr positive */ +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 */ +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; } @@ -276,36 +288,41 @@ 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 */ +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)); } +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; } @@ -316,40 +333,45 @@ void ddiv (int32 ac, d10 *dvr) int32 i, cryin; d10 sign, qu[2], dvd[4]; -dvd[0] = AC(ac); /* save dividend */ +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) */ +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 */ +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, 2)) = dvd[0]; /* remainder */ AC(ADDAC(ac, 3)) = dvd[1]; return; } - + /* Single precision floating add/subtract - 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 @@ -366,31 +388,38 @@ 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 */ +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); } @@ -400,18 +429,18 @@ return fpack (&a, NULL, FALSE); The extra 0 is accounted for by biasing the result exponent. */ -#define FP_V_SPM (FP_V_UFHI - (32 - FP_N_FHI - 1)) +#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 */ +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); } @@ -429,27 +458,30 @@ 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 */ +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) @@ -458,11 +490,11 @@ 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 */ +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 */ +fnorm (&a, 0); /* renormalize */ +return fpack (&a, NULL, FALSE); /* pack result */ } /* Float integer operand and round */ @@ -472,12 +504,12 @@ 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.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 */ +fnorm (&a, FP_URNDS); /* normalize, round */ +return fpack (&a, NULL, FALSE); /* pack result */ } /* Fix and truncate/round floating operand */ @@ -488,18 +520,21 @@ int32 sc; t_uint64 so; UFP a; -funpack (mb, 0, &a, AFRC); /* unpack operand */ +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) AC(ac) = 0; /* < 1/2? */ -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)); } +else if (a.exp < FP_BIAS) AC(ac) = 0; /* < 1/2? */ +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. @@ -511,40 +546,48 @@ int32 p1 = ADDAC (ac, 1); int32 ediff; UFP a, b, t; -if (inv) { DMOVN (rs); } /* subtract? -b */ +if (inv) { DMOVN (rs); } /* subtract? -b */ if ((AC(ac) | AC(p1)) == 0) funpack (rs[0], rs[1], &a, AFRC); - /* a == 0? sum = b */ + /* a == 0? sum = b */ else if ((rs[0] | rs[1]) == 0) funpack (AC(ac), AC(p1), &a, AFRC); - /* b == 0? sum = a */ + /* 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 */ + 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; } @@ -562,24 +605,25 @@ 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 (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 */ +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 = 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 */ +fnorm (&a, FP_URNDD); /* normalize, round */ +AC(ac) = fpack (&a, &AC(p1), FALSE); /* pack result */ return; } @@ -597,29 +641,34 @@ int32 i; t_uint64 qu = 0; UFP a, b; -funpack (AC(ac), AC(p1), &a, AFRC); /* unpack operands */ +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 */ +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) @@ -633,17 +682,22 @@ 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; /* 1s comp exp */ - if (sgn) { /* signed frac? */ - if (r->fhi) r->fhi = r->fhi | FP_UCRY; /* extend sign */ - else { - r->exp = r->exp + 1; - r->fhi = FP_UCRY | FP_UNORM; } } - else { /* abs frac */ - if (r->fhi) r->fhi = UNEG (r->fhi) & FP_UFRAC; - else { - r->exp = r->exp + 1; - r->fhi = FP_UNORM; } } } + r->exp = r->exp ^ FP_M_EXP; /* 1s comp exp */ + if (sgn) { /* signed frac? */ + if (r->fhi) r->fhi = r->fhi | FP_UCRY; /* extend sign */ + else { + r->exp = r->exp + 1; + r->fhi = FP_UCRY | FP_UNORM; + } + } + else { /* abs frac */ + if (r->fhi) r->fhi = UNEG (r->fhi) & FP_UFRAC; + else { + r->exp = r->exp + 1; + r->fhi = FP_UNORM; + } + } + } return; } @@ -654,29 +708,36 @@ void fnorm (UFP *a, t_int64 rnd) int32 i; static t_uint64 normmask[6] = { 0x6000000000000000, 0x7800000000000000, 0x7F80000000000000, - 0x7FFF800000000000, 0x7FFFFFFF80000000, 0x7FFFFFFFFFFFFFFF }; + 0x7FFF800000000000, 0x7FFFFFFF80000000, 0x7FFFFFFFFFFFFFFF + }; static int32 normtab[7] = { 1, 2, 4, 8, 16, 32, 63 }; extern a10 pager_PC; -if (a->fhi & FP_UCRY) { /* carry set? */ - printf ("%%PDP-10 FP: carry bit set at normalization, PC = %o\n", pager_PC); - a->flo = (a->flo >> 1) | ((a->fhi & 1) << 63); /* try to recover */ - a->fhi = a->fhi >> 1; /* but root cause */ - a->exp = a->exp + 1; } /* should be fixed! */ -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; } } +if (a->fhi & FP_UCRY) { /* carry set? */ + printf ("%%PDP-10 FP: carry bit set at normalization, PC = %o\n", pager_PC); + a->flo = (a->flo >> 1) | ((a->fhi & 1) << 63); /* try to recover */ + a->fhi = a->fhi >> 1; /* but root cause */ + a->exp = a->exp + 1; /* should be fixed! */ + } +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; } @@ -689,14 +750,16 @@ 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; + ((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 (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 index 52367833..7ee60771 100644 --- a/PDP10/pdp10_pag.c +++ b/PDP10/pdp10_pag.c @@ -1,6 +1,6 @@ /* pdp10_pag.c: PDP-10 paging subsystem simulator - Copyright (c) 1993-2004, Robert M Supnik + Copyright (c) 1993-2005, 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"), @@ -19,18 +19,18 @@ 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 + 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 + 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 + 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. @@ -45,10 +45,10 @@ 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 + 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 @@ -65,34 +65,34 @@ 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 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) +#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 */ +#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]; @@ -111,9 +111,9 @@ 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 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; @@ -122,29 +122,32 @@ 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 + 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) } }; + { UDATA (NULL, UNIT_FIX, PTBL_MEMSIZE) }, + { UDATA (NULL, UNIT_FIX, PTBL_MEMSIZE) } + }; REG pag_reg[] = { - { ORDATA (PANIC_EA, save_ea, PASIZE), REG_HRO }, - { NULL } }; + { 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 }; - + "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 @@ -161,62 +164,65 @@ 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 (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 */ +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 (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 */ +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 (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 */ +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 */ +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 */ +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; } @@ -224,22 +230,26 @@ 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 */ +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 */ +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; } @@ -247,25 +257,25 @@ 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 */ +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 */ +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? */ + (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 @@ -274,18 +284,19 @@ return; 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. + - 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) +#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) { @@ -300,32 +311,34 @@ int32 ptbl_fill (a10 ea, int32 *tbl, int32 mode) ITS has no MAP instruction, therefore, physical NXM traps are ok. */ -if (ITS) { /* ITS paging */ - int32 acc, decvpn, pte, vpn, ptead, xpte; - d10 ptewd; +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 */ + 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 @@ -335,61 +348,62 @@ if (ITS) { /* ITS paging */ user process tables. */ -else if (!T20) { /* TOPS-10 paging */ - int32 pte, vpn, ptead, xpte; - d10 ptewd; +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 */ + 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. + 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). + 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. + 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 */ +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 */ + 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 @@ -407,99 +421,112 @@ else { /* TOPS-20 paging */ 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 */ + 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 */ + 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 */ + 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) @@ -507,19 +534,25 @@ 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]; } + 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; } +else { + t = UBR_GETUBR (ubr); + upta = t << PAG_V_PN; + } return; } @@ -538,8 +571,10 @@ 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 */ +else { + if (pager_word & PF_HARD) val = pager_word; /* hard error */ + else val = val | PF_VIRT | ea; /* inaccessible */ + } return val; } @@ -550,7 +585,7 @@ a10 conmap (a10 ea, int32 mode, int32 sw) int32 xpte, *tbl; if (!PAGING) return ea; -set_dyn_ptrs (); /* in case changed */ +set_dyn_ptrs (); /* in case changed */ if (sw & SWMASK ('E')) tbl = eptbl; else if (sw & SWMASK ('U')) tbl = uptbl; else tbl = ptbl_cur; @@ -558,28 +593,31 @@ 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 */ +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 */ +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 */ +ebr = ea & EBR_MASK; /* store EBR */ +pag_reset (&pag_dev); /* clear page tables */ +set_dyn_ptrs (); /* set dynamic ptrs */ return FALSE; } @@ -592,14 +630,15 @@ 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 */ +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 */ +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; @@ -623,7 +662,7 @@ t_bool rdhsb (a10 ea, int32 prv) Write (ea, hsb, prv); return FALSE; } - + /* TOPS20 pager instructions */ t_bool wrspb (a10 ea, int32 prv) @@ -666,7 +705,7 @@ t_bool wrcstm (a10 ea, int32 prv) { cstm = Read (ea, prv); if ((cpu_unit.flags & UNIT_T20V41) && (ea == 040127)) - cstm = 0770000000000; + cstm = 0770000000000; return FALSE; } @@ -675,7 +714,7 @@ t_bool rdcstm (a10 ea, int32 prv) Write (ea, cstm, prv); return FALSE; } - + /* ITS pager instructions The KS10 does not implement the JPC option. */ @@ -770,7 +809,9 @@ Write (ADDA (ea, 1), dbr2, prv); Write (ADDA (ea, 2), quant, prv); return FALSE; } - + +/* Simulator interface routines */ + t_stat pag_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw) { int32 tbln = uptr - pag_unit; @@ -795,7 +836,8 @@ 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; } + 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 index db82ceb3..344668fc 100644 --- a/PDP10/pdp10_rp.c +++ b/PDP10/pdp10_rp.c @@ -19,32 +19,33 @@ 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 + 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 + rp RH/RP/RM moving head disks - 18-Mar-05 RMS Added attached test to detach routine - 20-Sep-04 RMS Fixed bugs in replicated state, RP vs RM accuracy - 04-Jan-04 RMS Changed sim_fsize calling sequence - 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 + 07-Jul-05 RMS Removed extraneous externs + 18-Mar-05 RMS Added attached test to detach routine + 20-Sep-04 RMS Fixed bugs in replicated state, RP vs RM accuracy + 04-Jan-04 RMS Changed sim_fsize calling sequence + 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 @@ -65,155 +66,155 @@ - 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))) -#define MBA_RP_CTRL 0 /* RP drive */ -#define MBA_RM_CTRL 1 /* RM drive */ +#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))) +#define MBA_RP_CTRL 0 /* RP drive */ +#define MBA_RM_CTRL 1 /* RM drive */ /* 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 */ +#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 */ +#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)) +#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 */ +#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) +#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) +#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 +#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 */ +#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 */ +#define AS_U0 0000001 /* unit 0 flag */ /* RPLA - 176720 - look ahead register */ -#define LA_V_SC 6 /* sector pos */ +#define LA_V_SC 6 /* sector pos */ /* RPDB - 176722 - data buffer */ /* RPMR - 176724 - maintenace register */ @@ -222,39 +223,39 @@ /* 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 +#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)) +#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 + 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 + 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 @@ -263,98 +264,98 @@ The RP07, despite its name, uses an RM-style controller. */ -#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 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 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 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 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 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) +#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 { - int32 sect; /* sectors */ - int32 surf; /* surfaces */ - int32 cyl; /* cylinders */ - int32 size; /* #blocks */ - int32 devtype; /* device type */ - int32 ctrl; /* ctrl type */ -}; + int32 sect; /* sectors */ + int32 surf; /* surfaces */ + int32 cyl; /* cylinders */ + int32 size; /* #blocks */ + int32 devtype; /* device type */ + int32 ctrl; /* ctrl type */ + }; struct drvtyp drv_tab[] = { - { RM03_SECT, RM03_SURF, RM03_CYL, RM03_SIZE, RM03_DEV, MBA_RM_CTRL }, - { RP04_SECT, RP04_SURF, RP04_CYL, RP04_SIZE, RP04_DEV, MBA_RP_CTRL }, - { RM80_SECT, RM80_SURF, RM80_CYL, RM80_SIZE, RM80_DEV, MBA_RM_CTRL }, - { RP06_SECT, RP06_SURF, RP06_CYL, RP06_SIZE, RP06_DEV, MBA_RP_CTRL }, - { RM05_SECT, RM05_SURF, RM05_CYL, RM05_SIZE, RM05_DEV, MBA_RM_CTRL }, - { RP07_SECT, RP07_SURF, RP07_CYL, RP07_SIZE, RP07_DEV, MBA_RM_CTRL }, - { 0 } }; - -extern d10 *M; /* memory */ + { RM03_SECT, RM03_SURF, RM03_CYL, RM03_SIZE, RM03_DEV, MBA_RM_CTRL }, + { RP04_SECT, RP04_SURF, RP04_CYL, RP04_SIZE, RP04_DEV, MBA_RP_CTRL }, + { RM80_SECT, RM80_SURF, RM80_CYL, RM80_SIZE, RM80_DEV, MBA_RM_CTRL }, + { RP06_SECT, RP06_SURF, RP06_CYL, RP06_SIZE, RP06_DEV, MBA_RP_CTRL }, + { RM05_SECT, RM05_SURF, RM05_CYL, RM05_SIZE, RM05_DEV, MBA_RM_CTRL }, + { RP07_SECT, RP07_SURF, RP07_CYL, RP07_SIZE, RP07_DEV, MBA_RM_CTRL }, + { 0 } + }; + +extern d10 *M; /* memory */ extern int32 int_req; -extern int32 int_vec[32]; -extern int32 ubmap[UBANUM][UMAP_MEMSIZE]; /* Unibus maps */ +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 rpcs2 = 0; /* control/status 2 */ -int32 rpdb = 0; /* data buffer */ -uint16 rpda[RP_NUMDR] = { 0 }; /* track/sector */ -uint16 rpds[RP_NUMDR] = { 0 }; /* drive status */ -uint16 rper1[RP_NUMDR] = { 0 }; /* error status 1 */ -uint16 rmhr[RP_NUMDR] = { 0 }; /* holding reg */ -uint16 rpmr[RP_NUMDR] = { 0 }; /* maint reg */ -uint16 rmmr2[RP_NUMDR] = { 0 }; /* maint reg 2 */ -uint16 rpof[RP_NUMDR] = { 0 }; /* offset */ -uint16 rpdc[RP_NUMDR] = { 0 }; /* cylinder */ -uint16 rper2[RP_NUMDR] = { 0 }; /* error status 2 */ -uint16 rper3[RP_NUMDR] = { 0 }; /* error status 3 */ -uint16 rpec1[RP_NUMDR] = { 0 }; /* ECC correction 1 */ -uint16 rpec2[RP_NUMDR] = { 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 */ +int32 rpcs1 = 0; /* control/status 1 */ +int32 rpwc = 0; /* word count */ +int32 rpba = 0; /* bus address */ +int32 rpcs2 = 0; /* control/status 2 */ +int32 rpdb = 0; /* data buffer */ +uint16 rpda[RP_NUMDR] = { 0 }; /* track/sector */ +uint16 rpds[RP_NUMDR] = { 0 }; /* drive status */ +uint16 rper1[RP_NUMDR] = { 0 }; /* error status 1 */ +uint16 rmhr[RP_NUMDR] = { 0 }; /* holding reg */ +uint16 rpmr[RP_NUMDR] = { 0 }; /* maint reg */ +uint16 rmmr2[RP_NUMDR] = { 0 }; /* maint reg 2 */ +uint16 rpof[RP_NUMDR] = { 0 }; /* offset */ +uint16 rpdc[RP_NUMDR] = { 0 }; /* cylinder */ +uint16 rper2[RP_NUMDR] = { 0 }; /* error status 2 */ +uint16 rper3[RP_NUMDR] = { 0 }; /* error status 3 */ +uint16 rpec1[RP_NUMDR] = { 0 }; /* ECC correction 1 */ +uint16 rpec2[RP_NUMDR] = { 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 }; -static char *rp_mapnam[MBA_RM_CTRL + 1] = { "RP", "RM" }; + 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); @@ -368,325 +369,377 @@ void set_rper (int32 flag, int32 drv); 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 + 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 } }; +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) } }; + { 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 (RPCS2, rpcs2, 16) }, - { ORDATA (RPDB, rpdb, 16) }, - { BRDATA (RPDA, rpda, 8, 16, RP_NUMDR) }, - { BRDATA (RPDS, rpds, 8, 16, RP_NUMDR) }, - { BRDATA (RPER1, rper1, 8, 16, RP_NUMDR) }, - { BRDATA (RPHR, rmhr, 8, 16, RP_NUMDR) }, - { BRDATA (RPOF, rpof, 8, 16, RP_NUMDR) }, - { BRDATA (RPDC, rpdc, 8, 16, RP_NUMDR) }, - { BRDATA (RPER2, rper2, 8, 16, RP_NUMDR) }, - { BRDATA (RPER3, rper3, 8, 16, RP_NUMDR) }, - { BRDATA (RPEC1, rpec1, 8, 16, RP_NUMDR) }, - { BRDATA (RPEC2, rpec2, 8, 16, RP_NUMDR) }, - { BRDATA (RMMR, rpmr, 8, 16, RP_NUMDR) }, - { BRDATA (RMMR2, rmmr2, 8, 16, RP_NUMDR) }, - { 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 } }; + { ORDATA (RPCS1, rpcs1, 16) }, + { ORDATA (RPWC, rpwc, 16) }, + { ORDATA (RPBA, rpba, 16) }, + { ORDATA (RPCS2, rpcs2, 16) }, + { ORDATA (RPDB, rpdb, 16) }, + { BRDATA (RPDA, rpda, 8, 16, RP_NUMDR) }, + { BRDATA (RPDS, rpds, 8, 16, RP_NUMDR) }, + { BRDATA (RPER1, rper1, 8, 16, RP_NUMDR) }, + { BRDATA (RPHR, rmhr, 8, 16, RP_NUMDR) }, + { BRDATA (RPOF, rpof, 8, 16, RP_NUMDR) }, + { BRDATA (RPDC, rpdc, 8, 16, RP_NUMDR) }, + { BRDATA (RPER2, rper2, 8, 16, RP_NUMDR) }, + { BRDATA (RPER3, rper3, 8, 16, RP_NUMDR) }, + { BRDATA (RPEC1, rpec1, 8, 16, RP_NUMDR) }, + { BRDATA (RPEC2, rpec2, 8, 16, RP_NUMDR) }, + { BRDATA (RMMR, rpmr, 8, 16, RP_NUMDR) }, + { BRDATA (RMMR2, rmmr2, 8, 16, RP_NUMDR) }, + { 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 } }; + { 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 }; - + "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; } +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[drv] = rpda[drv] & ~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[drv]; - break; -case 013: /* RPDT */ - *data = drv_tab[dtype].devtype; - break; -case 014: /* RPSN */ - *data = 020 | (drv + 1); - break; -case 015: /* RPOF */ - *data = rpof[drv] = rpof[drv] & ~OF_MBZ; - break; -case 016: /* RPDC */ - *data = rpdc[drv] = rpdc[drv] & ~DC_MBZ; - break; -case 017: /* RPCC, RMHR */ - if (drv_tab[dtype].ctrl == MBA_RP_CTRL) /* RP is CC */ - *data = rp_unit[drv].CYL; - else *data = rmhr[drv] ^ 0177777; /* RM is HR */ - break; -case 020: /* RPER2, RMMR2 */ - if (drv_tab[dtype].ctrl == MBA_RP_CTRL) /* RP is ER2 */ - *data = rper2[drv]; - else *data = rmmr2[drv]; /* RM is MR2 */ - break; -case 021: /* RPER3, RMER2 */ - if (drv_tab[dtype].ctrl == MBA_RP_CTRL) /* RP is ER3 */ - *data = rper3[drv]; - else *data = rper2[drv]; /* RM is ER2 */ - break; -case 022: /* RPEC1 */ - *data = rpec1[drv]; - break; -case 023: /* RPEC2 */ - *data = rpec2[drv]; - break; -default: /* all others */ - set_rper (ER1_ILR, drv); - update_rpcs (0, drv); - break; } +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[drv] = rpda[drv] & ~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[drv]; + break; + + case 013: /* RPDT */ + *data = drv_tab[dtype].devtype; + break; + + case 014: /* RPSN */ + *data = 020 | (drv + 1); + break; + + case 015: /* RPOF */ + *data = rpof[drv] = rpof[drv] & ~OF_MBZ; + break; + + case 016: /* RPDC */ + *data = rpdc[drv] = rpdc[drv] & ~DC_MBZ; + break; + + case 017: /* RPCC, RMHR */ + if (drv_tab[dtype].ctrl == MBA_RP_CTRL) /* RP is CC */ + *data = rp_unit[drv].CYL; + else *data = rmhr[drv] ^ 0177777; /* RM is HR */ + break; + + case 020: /* RPER2, RMMR2 */ + if (drv_tab[dtype].ctrl == MBA_RP_CTRL) /* RP is ER2 */ + *data = rper2[drv]; + else *data = rmmr2[drv]; /* RM is MR2 */ + break; + + case 021: /* RPER3, RMER2 */ + if (drv_tab[dtype].ctrl == MBA_RP_CTRL) /* RP is ER3 */ + *data = rper3[drv]; + else *data = rper2[drv]; /* RM is ER2 */ + break; + + case 022: /* RPEC1 */ + *data = rpec1[drv]; + break; + + case 023: /* RPEC2 */ + *data = rpec2[drv]; + break; + + default: /* all others */ + set_rper (ER1_ILR, drv); + update_rpcs (0, drv); + break; + } return SCPE_OK; } - + t_stat rp_wr (int32 data, int32 PA, int32 access) { int32 cs1f, drv, dtype, i, j; UNIT *uptr; -cs1f = 0; /* no int on cs1 upd */ -drv = GET_UNIT (rpcs2); /* get current unit */ -dtype = GET_DTYPE (rp_unit[drv].flags); /* get drive type */ -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? */ - set_rper (ER1_RMR, drv); /* won't write */ - update_rpcs (0, drv); - return SCPE_OK; } +cs1f = 0; /* no int on cs1 upd */ +drv = GET_UNIT (rpcs2); /* get current unit */ +dtype = GET_DTYPE (rp_unit[drv].flags); /* get drive type */ +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? */ + set_rper (ER1_RMR, drv); /* won't write */ + update_rpcs (0, drv); + return SCPE_OK; + } rmhr[drv] = data; -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)) - set_rper (ER1_RMR, drv); /* 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) && (PA & 1)) data = data << 8; - rpda[drv] = 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) && (PA & 1)) data = data << 8; - 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) && (PA & 1)) data = data << 8; - rpmr[drv] = data; - break; -case 015: /* RPOF */ - rpof[drv] = data & ~OF_MBZ; - break; -case 016: /* RPDC */ - if ((access == WRITEB) && (PA & 1)) data = data << 8; - rpdc[drv] = data & ~DC_MBZ; - break; -case 005: /* RPDS */ -case 010: /* RPLA */ -case 013: /* RPDT */ -case 014: /* RPSN */ -case 017: /* RPCC, RMHR */ -case 020: /* RPER2, RMMR2 */ -case 021: /* RPER3, RMER2 */ -case 022: /* RPEC1 */ -case 023: /* RPEC2 */ - break; /* read only */ -default: /* all others */ - set_rper (ER1_ILR, drv); - break; } /* end switch */ -update_rpcs (cs1f, drv); /* update status */ +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)) + set_rper (ER1_RMR, drv); /* 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) && (PA & 1)) data = data << 8; + rpda[drv] = 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) && (PA & 1)) data = data << 8; + 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) && (PA & 1)) data = data << 8; + rpmr[drv] = data; + break; + + case 015: /* RPOF */ + rpof[drv] = data & ~OF_MBZ; + break; + + case 016: /* RPDC */ + if ((access == WRITEB) && (PA & 1)) data = data << 8; + rpdc[drv] = data & ~DC_MBZ; + break; + + case 005: /* RPDS */ + case 010: /* RPLA */ + case 013: /* RPDT */ + case 014: /* RPSN */ + case 017: /* RPCC, RMHR */ + case 020: /* RPER2, RMMR2 */ + case 021: /* RPER3, RMER2 */ + case 022: /* RPEC1 */ + case 023: /* RPEC2 */ + break; /* read only */ + + default: /* all others */ + set_rper (ER1_ILR, drv); + 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) @@ -694,91 +747,101 @@ 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? */ - set_rper (ER1_ILF, drv); /* set err, ATN */ - 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[drv]; /* assume seek, sch */ +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? */ + set_rper (ER1_ILF, drv); /* set err, ATN */ + 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[drv]; /* assume seek, sch */ -switch (fnc) { /* case on function */ -case FNC_DCLR: /* drive clear */ - rpda[drv] = 0; /* clear disk addr */ - rper1[drv] = rper2[drv] = rper3[drv] = 0; /* clear errors */ -case FNC_NOP: /* no operation */ -case FNC_RELEASE: /* port release */ - return; +switch (fnc) { /* case on function */ -case FNC_PRESET: /* read-in preset */ - rpdc[drv] = 0; /* clear disk addr */ - rpda[drv] = 0; - rpof[drv] = 0; /* clear offset */ -case FNC_PACK: /* pack acknowledge */ - rpds[drv] = rpds[drv] | DS_VV; /* set volume valid */ - return; + case FNC_DCLR: /* drive clear */ + rpda[drv] = 0; /* clear disk addr */ + rper1[drv] = rper2[drv] = rper3[drv] = 0; /* clear errors */ + case FNC_NOP: /* no operation */ + case FNC_RELEASE: /* port release */ + return; -case FNC_OFFSET: /* offset mode */ -case FNC_RETURN: - if ((uptr->flags & UNIT_ATT) == 0) { /* not attached? */ - set_rper (ER1_UNS, drv); /* unsafe */ - break; } - rpds[drv] = (rpds[drv] & ~DS_RDY) | DS_PIP; /* set positioning */ - sim_activate (uptr, rp_swait); /* time operation */ - return; + case FNC_PRESET: /* read-in preset */ + rpdc[drv] = 0; /* clear disk addr */ + rpda[drv] = 0; + rpof[drv] = 0; /* clear offset */ + case FNC_PACK: /* pack acknowledge */ + rpds[drv] = rpds[drv] | DS_VV; /* set volume valid */ + 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? */ - set_rper (ER1_UNS, drv); /* unsafe */ - break; } - if ((GET_CY (dc) >= drv_tab[dtype].cyl) || /* bad cylinder */ - (GET_SF (rpda[drv]) >= drv_tab[dtype].surf) || /* bad surface */ - (GET_SC (rpda[drv]) >= drv_tab[dtype].sect)) { /* or bad sector? */ - set_rper (ER1_IAE, drv); - 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_OFFSET: /* offset mode */ + case FNC_RETURN: + if ((uptr->flags & UNIT_ATT) == 0) { /* not attached? */ + set_rper (ER1_UNS, drv); /* unsafe */ + break; + } + rpds[drv] = (rpds[drv] & ~DS_RDY) | DS_PIP; /* set positioning */ + sim_activate (uptr, rp_swait); /* time operation */ + 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? */ - set_rper (ER1_UNS, drv); /* 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]) >= drv_tab[dtype].surf) || /* bad surface */ - (GET_SC (rpda[drv]) >= drv_tab[dtype].sect)) { /* or bad sector? */ - set_rper (ER1_IAE, drv); - 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; + 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? */ + set_rper (ER1_UNS, drv); /* unsafe */ + break; + } + if ((GET_CY (dc) >= drv_tab[dtype].cyl) || /* bad cylinder */ + (GET_SF (rpda[drv]) >= drv_tab[dtype].surf) || /* bad surface */ + (GET_SC (rpda[drv]) >= drv_tab[dtype].sect)) { /* or bad sector? */ + set_rper (ER1_IAE, drv); + 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; -default: /* all others */ - set_rper (ER1_ILF, drv); /* not supported */ - break; } -update_rpcs (CS1_SC, drv); /* req intr */ + 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? */ + set_rper (ER1_UNS, drv); /* 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]) >= drv_tab[dtype].surf) || /* bad surface */ + (GET_SC (rpda[drv]) >= drv_tab[dtype].sect)) { /* or bad sector? */ + set_rper (ER1_IAE, drv); + 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 */ + set_rper (ER1_ILF, drv); /* not supported */ + break; + } + +update_rpcs (CS1_SC, drv); /* req intr */ return; } - + /* Service unit timeout Complete movement or data transfer command @@ -794,28 +857,32 @@ 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 */ +dtype = GET_DTYPE (uptr->flags); /* get drive type */ +drv = (int32) (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; +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 @@ -824,97 +891,111 @@ case FNC_SEEK: /* seek */ 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 */ +#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? */ - set_rper (ER1_WLE, drv); /* 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[drv], rpda[drv], dtype) * RP_NUMWD; /* get disk addr */ - if ((da + wc10) > drv_tab[dtype].size) { /* disk overrun? */ - set_rper (ER1_AOE, drv); - if (wc10 > (drv_tab[dtype].size - da)) - wc10 = drv_tab[dtype].size - da; } + case FNC_WRITE: /* write */ + if (uptr->flags & UNIT_WPRT) { /* write locked? */ + set_rper (ER1_WLE, drv); /* 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[drv], rpda[drv], dtype) * RP_NUMWD; /* get disk addr */ + if ((da + wc10) > drv_tab[dtype].size) { /* disk overrun? */ + set_rper (ER1_AOE, drv); + 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 */ + 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[drv] = da % drv_tab[dtype].sect; - da = da / drv_tab[dtype].sect; - rpda[drv] = rpda[drv] | ((da % drv_tab[dtype].surf) << DA_V_SF); - rpdc[drv] = da / drv_tab[dtype].surf; + 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[drv] = da % drv_tab[dtype].sect; + da = da / drv_tab[dtype].sect; + rpda[drv] = rpda[drv] | ((da % drv_tab[dtype].surf) << DA_V_SF); + rpdc[drv] = da / drv_tab[dtype].surf; + + if (err != 0) { /* error? */ + set_rper (ER1_PAR, drv); /* 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 */ - if (err != 0) { /* error? */ - set_rper (ER1_PAR, drv); /* 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; } - + /* Set drive error */ void set_rper (int32 flag, int32 drv) @@ -938,15 +1019,15 @@ 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 ((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[drv] | rper3[drv]) - rpds[drv] = rpds[drv] | DS_ERR; + rpds[drv] = rpds[drv] | DS_ERR; else rpds[drv] = rpds[drv] & ~DS_ERR; rpcs1 = (rpcs1 & ~(CS1_SC | CS1_MCPE | CS1_MBZ | CS1_DRV)) | CS1_DVA | flag; @@ -955,9 +1036,9 @@ 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 (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; + int_req = int_req | INT_RP; else int_req = int_req & ~INT_RP; return; } @@ -966,11 +1047,11 @@ return; int32 rp_inta (void) { -rpcs1 = rpcs1 & ~CS1_IE; /* clear int enable */ -rpiff = 0; /* clear CSTB INTR */ -return VEC_RP; /* acknowledge */ +rpcs1 = rpcs1 & ~CS1_IE; /* clear int enable */ +rpiff = 0; /* clear CSTB INTR */ +return VEC_RP; /* acknowledge */ } - + /* Device reset */ t_stat rp_reset (DEVICE *dptr) @@ -981,27 +1062,28 @@ UNIT *uptr; rpcs1 = CS1_DVA | CS1_DONE; rpcs2 = CS2_IR | CS2_OR; rpba = rpwc = 0; -rpiff = 0; /* clear CSTB INTR */ -int_req = int_req & ~INT_RP; /* clear intr req */ +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; - rper2[i] = 0; - rper3[i] = 0; - rpda[i] = 0; - rpdc[i] = 0; - rpmr[i] = 0; - rpof[i] = 0; - rpec1[i] = 0; - rpec2[i] = 0; - rmmr2[i] = 0; - rmhr[i] = 0; } + 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; + rper2[i] = 0; + rper3[i] = 0; + rpda[i] = 0; + rpdc[i] = 0; + rpmr[i] = 0; + rpof[i] = 0; + rpec1[i] = 0; + rpec2[i] = 0; + rmmr2[i] = 0; + rmhr[i] = 0; + } return SCPE_OK; } @@ -1015,19 +1097,21 @@ 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 */ +drv = (int32) (uptr - rp_dev.units); /* get drv number */ rpds[drv] = DS_ATA | DS_MOL | DS_RDY | DS_DPR | - ((uptr->flags & UNIT_WPRT)? DS_WRL: 0); + ((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 ((uptr->flags & UNIT_AUTO) == 0) return SCPE_OK; /* autosize? */ if ((p = sim_fsize (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; } } + uptr->flags = (uptr->flags & ~UNIT_DTYPE) | (i << UNIT_V_DTYPE); + uptr->capac = drv_tab[i].size; + return SCPE_OK; + } + } return SCPE_OK; } @@ -1037,16 +1121,17 @@ t_stat rp_detach (UNIT *uptr) { int32 drv; -if (!(uptr->flags & UNIT_ATT)) return SCPE_OK; /* attached? */ -drv = uptr - rp_dev.units; /* get drv number */ +if (!(uptr->flags & UNIT_ATT)) return SCPE_OK; /* attached? */ +drv = (int32) (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 */ + 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); } @@ -1063,102 +1148,102 @@ return SCPE_OK; /* Device bootstrap */ -#define BOOT_START 0377000 /* start */ +#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 */ -}; + 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 */ -}; + 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) { @@ -1167,7 +1252,7 @@ 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]; + 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 index 3dd677fd..47b2ffde 100644 --- a/PDP10/pdp10_sys.c +++ b/PDP10/pdp10_sys.c @@ -1,6 +1,6 @@ /* pdp10_sys.c: PDP-10 simulator interface - Copyright (c) 1993-2004, Robert M Supnik + Copyright (c) 1993-2005, 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"), @@ -19,21 +19,22 @@ 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 + 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 + 22-Jul-05 RMS Fixed warning from Solaris C (from Doug Gwyn) + 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" @@ -53,12 +54,12 @@ 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 + 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"; @@ -68,59 +69,61 @@ 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 }; + &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" }; - + "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 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 +#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 + -count,,origin-1 + word + : + word + checksum (includes IOWD) + : + JRST start */ d10 getrimw (FILE *fileref) @@ -130,10 +133,12 @@ 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++; } } + if ((tmp = getc (fileref)) == EOF) return -1; + if (tmp & 0200) { + word = (word << 6) | ((d10) tmp & 077); + i++; + } + } return word; } @@ -143,27 +148,29 @@ 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; +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 */ + break; + } /* end else */ + } /* end for */ +return SCPE_OK; } /* SAV file loader @@ -171,12 +178,12 @@ return SCPE_FMT; SAV format is a disk file format (36b words). It consists of blocks containing: - -count,,origin-1 - word - : - word - : - JRST start + -count,,origin-1 + word + : + word + : + JRST start */ t_stat load_sav (FILE *fileref) @@ -185,50 +192,52 @@ 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; +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 */ + break; + } /* end else */ + } /* end for */ +return SCPE_OK; } - + /* 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 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 + 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 + 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) +#define DIRSIZ (2 * PAG_SIZE) t_stat load_exe (FILE *fileref) { @@ -237,59 +246,66 @@ int32 ndir, entvec, i, j, k, cont, bsz, bty, rpt, wc; int32 fpage, mpage; a10 ma; -ndir = entvec = 0; /* no dir, entvec */ +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); +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 */ -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 */ + 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 */ + } while (cont); /* end do */ + +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 */ + 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) @@ -298,54 +314,63 @@ 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); } +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 +#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 }; + 0700340000000, 0777777777777 + }; static const char *opcode[] = { -"XCTR", "XCTI", /* ITS only */ +"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 */ +"PORTAL", "JRSTF", "HALT", /* AC defines op */ "XJRSTF", "XJEN", "XPCW", "JEN", "SFM", "XJRST", "IBP", "JFOV", "JCRY1", "JCRY0", "JCRY", "JOV", @@ -418,19 +443,19 @@ static const char *opcode[] = { "TRO", "TLO", "TROE", "TLOE", "TROA", "TLOA", "TRON", "TLON", "TDO", "TSO", "TDOE", "TSOE", "TDOA", "TSOA", "TDON", "TSON", -"UMOVE", "UMOVEM", /* KS10 I/O */ +"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 */ +"BLKI", "DATAI", "BLKO", "DATAO", /* classic I/O */ "CONO", "CONI", "CONSZ", "CONSO", "CLEAR", "CLEARI", "CLEARM", "CLEARB", -"OR", "ORI", "ORM", "ORB", "XMOVEI", "XHLLI", /* alternate ops */ +"OR", "ORI", "ORM", "ORB", "XMOVEI", "XHLLI", /* alternate ops */ - "CMPSL", "CMPSE", "CMPSLE", /* extended ops */ + "CMPSL", "CMPSE", "CMPSLE", /* extended ops */ "EDIT", "CMPSGE", "CMPSN", "CMPSG", "CVTDBO", "CVTDBT", "CVTBDO", "CVTBDT", "MOVSO", "MOVST", "MOVSLJ", "MOVSRJ", @@ -438,7 +463,8 @@ static const char *opcode[] = { "GFIX", "GDFIXR", "GFIXR", "DGFLTR", "GFLTR", "GFSC", -NULL }; +NULL +}; static const d10 opc_val[] = { 0102000000000+I_AC+I_ITS, 0103000000000+I_AC+I_ITS, @@ -605,51 +631,57 @@ static const d10 opc_val[] = { 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 }; + -1 + }; -#define NUMDEV 6 +#define NUMDEV 6 static const char *devnam[NUMDEV] = { - "APR", "PI", "PAG", "CCA", "TIM", "MTR"}; + "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 + *of = output stream + addr = current PC + *val = pointer to values + *uptr = pointer to unit + sw = switches Outputs: - return = status code + 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) + 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 ('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 */ @@ -658,38 +690,42 @@ 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 */ +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 + *cptr = pointer to input string + *status = pointer to error status Outputs: - val = output value + val = output value */ t_value get_opnd (char *cptr, t_stat *status) @@ -698,38 +734,41 @@ int32 sign = 0; t_value val, xr = 0, ind = 0; char *tptr; -*status = SCPE_ARG; /* assume fail */ +*status = SCPE_ARG; /* assume fail */ if (*cptr == '@') { - ind = INST_IND; - cptr++; } + ind = INST_IND; + cptr++; + } if (*cptr == '+') cptr++; else if (*cptr == '-') { - sign = 1; - 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; } + 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 + *cptr = pointer to input string + addr = current PC + uptr = pointer to unit + *val = pointer to output values + sw = switches Outputs: - status = error status + status = error status */ t_stat parse_sym (char *cptr, t_addr addr, UNIT *uptr, t_value *val, int32 sw) @@ -742,57 +781,70 @@ 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 (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 (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 (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; } + 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 */ +/* Instruction parse */ -cptr = get_glyph (cptr, gbuf, 0); /* get opcode */ +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? */ +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); + } + } /* fall through */ + 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 index 8d7d1c52..3029d54b 100644 --- a/PDP10/pdp10_tim.c +++ b/PDP10/pdp10_tim.c @@ -1,6 +1,6 @@ /* pdp10_tim.c: PDP-10 tim subsystem simulator - Copyright (c) 1993-2004, Robert M Supnik + Copyright (c) 1993-2005, 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"), @@ -19,48 +19,48 @@ 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 + 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 + tim timer subsystem - 02-Feb-04 RMS Exported variables needed by Ethernet simulator - 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 + 02-Feb-04 RMS Exported variables needed by Ethernet simulator + 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) +#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 */ +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 */ /* Exported variables */ -int32 clk_tps = TIM_TPS; /* clock ticks/sec */ -int32 tmr_poll = TIM_DELAY; /* clock poll */ +int32 clk_tps = TIM_TPS; /* clock ticks/sec */ +int32 tmr_poll = TIM_DELAY; /* clock poll */ DEVICE tim_dev; t_stat tcu_rd (int32 *data, int32 PA, int32 access); @@ -75,9 +75,9 @@ extern int32 pi_eval (void); /* TIM data structures - tim_dev TIM device descriptor - tim_unit TIM unit descriptor - tim_reg TIM register list + 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 }; @@ -85,29 +85,32 @@ 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 } }; + { 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 } }; + { 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 }; - + "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) @@ -121,7 +124,7 @@ 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); + (CLRS (Read (INCA (ea), prv)) >> TIM_N_HWRE); return FALSE; } @@ -137,32 +140,34 @@ period = Read (ea, prv); ttg = period; return FALSE; } - + /* Timer routines - tim_svc process event (timer tick) - tim_reset process reset + 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 */ -tmr_poll = t; /* set timer poll */ -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 */ +t = diagflg? tim_unit.wait: sim_rtc_calb (TIM_TPS); /* calibrate clock */ +sim_activate (&tim_unit, t); /* reactivate unit */ +tmr_poll = t; /* set timer poll */ +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; } @@ -170,15 +175,15 @@ t_stat tim_reset (DEVICE *dptr) { int32 t; -period = ttg = 0; /* clear timer */ -apr_flg = apr_flg & ~APRF_TIM; /* clear interrupt */ -t = sim_rtc_init (tim_unit.wait); /* init timer */ -sim_activate (&tim_unit, t); /* activate unit */ -tmr_poll = t; /* set timer poll */ -tmxr_poll = t * DZ_MULT; /* set mux poll */ +period = ttg = 0; /* clear timer */ +apr_flg = apr_flg & ~APRF_TIM; /* clear interrupt */ +t = sim_rtc_init (tim_unit.wait); /* init timer */ +sim_activate (&tim_unit, t); /* activate unit */ +tmr_poll = t; /* set timer poll */ +tmxr_poll = t * DZ_MULT; /* set mux poll */ return SCPE_OK; } - + /* Time of year clock */ t_stat tcu_rd (int32 *data, int32 PA, int32 access) @@ -186,27 +191,33 @@ 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? */ +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; + 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 */ +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 index a455942f..8288cca1 100644 --- a/PDP10/pdp10_tu.c +++ b/PDP10/pdp10_tu.c @@ -19,53 +19,55 @@ 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 + 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 + tu RH11/TM03/TU45 magtape - 31-Mar-05 RMS Fixed bug, ERASE/WREOF incorrectly clear CS1 - Fixed inaccuracies in error reporting - 18-Mar-05 RMS Added attached test to detach routine - 23-Oct-04 RMS Fixed setting done on non data transfers - 01-Oct-04 RMS Modified to set FCE on read short record, eof - Implemented write check - TM03 uses only den<2> for validity test - TMK is cleared by new motion command, not DCLR - 14-Sep-04 RMS Fixed RIP value - 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 + 16-Aug-05 RMS Fixed C++ declaration and cast problems + 07-Jul-05 RMS Removed extraneous externs + 31-Mar-05 RMS Fixed bug, ERASE/WREOF incorrectly clear CS1 + Fixed inaccuracies in error reporting + 18-Mar-05 RMS Added attached test to detach routine + 23-Oct-04 RMS Fixed setting done on non data transfers + 01-Oct-04 RMS Modified to set FCE on read short record, eof + Implemented write check + TM03 uses only den<2> for validity test + TMK is cleared by new motion command, not DCLR + 14-Sep-04 RMS Fixed RIP value + 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 + 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. @@ -89,241 +91,246 @@ #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 */ +#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_N_FNC (CS1_M_FNC + 1) -#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)) +#define CS1_GO CSR_GO /* go */ +#define CS1_V_FNC 1 /* function pos */ +#define CS1_M_FNC 037 /* function mask */ +#define CS1_N_FNC (CS1_M_FNC + 1) +#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 */ +#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 */ -#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) +#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 */ +#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_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) +#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 */ +#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 */ +#define AS_U0 0000001 /* unit 0 flag */ /* MTCC - 172460 - check character, read only */ -#define CC_MBZ 0177000 /* must be zero */ +#define CC_MBZ 0177000 /* must be zero */ /* MTDB - 172462 - data buffer */ /* MTMR - 172464 - maintenance register */ -#define MR_RW 0177637 /* read/write */ +#define MR_RW 0177637 /* read/write */ /* MTDT - 172466 - drive type */ -#define DT_NSA 0100000 /* not sect addr */ -#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 */ +#define DT_NSA 0100000 /* not sect addr */ +#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 TC_RIP ((TC_800 << TC_V_DEN) || (TC_10C << TC_V_FMT)) -#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) +#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 TC_RIP ((TC_800 << TC_V_DEN) || (TC_10C << TC_V_FMT)) +#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; } \ +#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 d10 *M; /* memory */ extern int32 int_req; -extern int32 int_vec[32]; -extern int32 ubmap[UBANUM][UMAP_MEMSIZE]; /* Unibus map */ +extern int32 ubmap[UBANUM][UMAP_MEMSIZE]; /* Unibus map */ extern int32 ubcs[UBANUM]; extern UNIT cpu_unit; extern int32 sim_switches; extern FILE *sim_deb; -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 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 + }; static char *tu_fname[CS1_N_FNC] = { - "NOP", "UNLD", "2", "REW", "FCLR", "5", "6", "7", - "RIP", "11", "ERASE", "WREOF", "SPCF", "SPCR", "16", "17", - "20", "21", "22", "23", "WRCHKF", "25", "26", "WRCHKR", - "WRITE", "31", "32", "33", "READF", "35", "36" "READR" }; -static uint8 *xbuf = NULL; /* xfer buffer */ + "NOP", "UNLD", "2", "REW", "FCLR", "5", "6", "7", + "RIP", "11", "ERASE", "WREOF", "SPCF", "SPCR", "16", "17", + "20", "21", "22", "23", "WRCHKF", "25", "26", "WRCHKR", + "WRITE", "31", "32", "33", "READF", "35", "36" "READR" + }; +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); @@ -340,234 +347,280 @@ t_stat tu_map_err (UNIT *uptr, t_stat st, t_bool qdt); /* TU data structures - tu_dev TU device descriptor - tu_unit TU unit list - tu_reg TU register list - tu_mod TU modifier list + 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 } }; +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) } }; + { 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 } }; + { 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 } }; + { 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 | DEV_DEBUG }; - + "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 | DEV_DEBUG + }; + /* 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; } +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_NSA | 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 */ + set_tuer (ER_ILR); + update_tucs (0, drv); + break; + } -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_NSA | 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 */ - set_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? */ - set_tuer (ER_RMR); /* won't write */ - update_tucs (0, drv); - return SCPE_OK; } +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? */ + set_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) set_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 */ - set_tuer (ER_ILR); - break; } /* end switch */ -update_tucs (cs1f, drv); /* update status */ +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) set_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 */ + set_tuer (ER_ILR); + break; + } /* end switch */ + +update_tucs (cs1f, drv); /* update status */ return SCPE_OK; } - + /* New magtape command */ void tu_go (int32 drv) @@ -575,125 +628,141 @@ 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 */ +fnc = GET_FNC (tucs1); /* get function */ +den = GET_DEN (tutc); /* get density */ +uptr = tu_dev.units + drv; /* get unit */ if (DEBUG_PRS (tu_dev)) fprintf (sim_deb, - ">>TU%d STRT: fnc=%s, cs1=%06o, cs2=%06o, ba=%06o, wc=%06o, fc=%06o, fs=%06o, er=%06o, pos=%d\n", - drv, tu_fname[fnc], tucs1, tucs2, tuba, tuwc, tufc, tufs, tuer, uptr->pos); -if ((fnc != FNC_FCLR) && /* not clear & err */ - ((tufs & FS_ERR) || sim_is_active (uptr))) { /* or in motion? */ - set_tuer (ER_ILF); /* set err, ATN */ - 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 */ + ">>TU%d STRT: fnc=%s, cs1=%06o, cs2=%06o, ba=%06o, wc=%06o, fc=%06o, fs=%06o, er=%06o, pos=%d\n", + drv, tu_fname[fnc], tucs1, tucs2, tuba, tuwc, tufc, tufs, tuer, uptr->pos); +if ((fnc != FNC_FCLR) && /* not clear & err */ + ((tufs & FS_ERR) || sim_is_active (uptr))) { /* or in motion? */ + set_tuer (ER_ILF); /* set err, ATN */ + 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_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_RIP; /* density = 800 */ - sim_tape_rewind (&tu_unit[0]); /* rewind unit 0 */ - tu_unit[0].USTAT = 0; - tucs1 = tucs1 & ~CS1_GO; - tufs = tufs & ~FS_TMK; - return; +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_ERR); + sim_cancel (uptr); /* reset drive */ + uptr->USTAT = 0; + case FNC_NOP: + tucs1 = tucs1 & ~CS1_GO; /* no operation */ + return; -case FNC_UNLOAD: /* unload */ - if ((uptr->flags & UNIT_ATT) == 0) { /* unattached? */ - set_tuer (ER_UNS); - break; } - detach_unit (uptr); - uptr->USTAT = FS_REW; - sim_activate (uptr, tu_time); - tucs1 = tucs1 & ~CS1_GO; - tufs = tufs & ~FS_TMK; - return; -case FNC_REWIND: - if ((uptr->flags & UNIT_ATT) == 0) { /* unattached? */ - set_tuer (ER_UNS); - break; } - uptr->USTAT = FS_PIP | FS_REW; - sim_activate (uptr, tu_time); - tucs1 = tucs1 & ~CS1_GO; - tufs = tufs & ~FS_TMK; - return; + case FNC_RIP: /* read-in preset */ + tutc = TC_RIP; /* density = 800 */ + sim_tape_rewind (&tu_unit[0]); /* rewind unit 0 */ + tu_unit[0].USTAT = 0; + tucs1 = tucs1 & ~CS1_GO; + tufs = tufs & ~FS_TMK; + return; -case FNC_SPACEF: - space_test = FS_EOT; -case FNC_SPACER: - if ((uptr->flags & UNIT_ATT) == 0) { /* unattached? */ - set_tuer (ER_UNS); - break; } - if ((tufs & space_test) || ((tutc & TC_FCS) == 0)) { - set_tuer (ER_NXF); - break; } - uptr->USTAT = FS_PIP; - goto GO_XFER; + case FNC_UNLOAD: /* unload */ + if ((uptr->flags & UNIT_ATT) == 0) { /* unattached? */ + set_tuer (ER_UNS); + break; + } + detach_unit (uptr); + uptr->USTAT = FS_REW; + sim_activate (uptr, tu_time); + tucs1 = tucs1 & ~CS1_GO; + tufs = tufs & ~FS_TMK; + return; -case FNC_WREOF: /* write tape mark */ -case FNC_ERASE: /* erase */ - if ((uptr->flags & UNIT_ATT) == 0) { /* unattached? */ - set_tuer (ER_UNS); - break; } - if (sim_tape_wrp (uptr)) { /* write locked? */ - set_tuer (ER_NXF); - break; } - if (fmt_test[GET_FMT (tutc)] == 0) { /* invalid format? */ - set_tuer (ER_FER); - break; } - if (uptr->UDENS == UD_UNK) uptr->UDENS = den; /* set dens */ - uptr->USTAT = 0; - goto GO_XFER; + case FNC_REWIND: + if ((uptr->flags & UNIT_ATT) == 0) { /* unattached? */ + set_tuer (ER_UNS); + break; + } + uptr->USTAT = FS_PIP | FS_REW; + sim_activate (uptr, tu_time); + tucs1 = tucs1 & ~CS1_GO; + tufs = tufs & ~FS_TMK; + return; -case FNC_WCHKR: /* wchk = read */ -case FNC_READR: /* read rev */ - if (tufs & FS_BOT) { /* beginning of tape? */ - set_tuer (ER_NXF); - break; } - goto DATA_XFER; + case FNC_SPACEF: + space_test = FS_EOT; + case FNC_SPACER: + if ((uptr->flags & UNIT_ATT) == 0) { /* unattached? */ + set_tuer (ER_UNS); + break; + } + if ((tufs & space_test) || ((tutc & TC_FCS) == 0)) { + set_tuer (ER_NXF); + break; + } + uptr->USTAT = FS_PIP; + goto GO_XFER; -case FNC_WRITE: /* write */ - if (((tutc & TC_FCS) == 0) || /* frame cnt = 0? */ - ((den == TC_800) && (tufc > 0777765))) { /* NRZI, fc < 13? */ - set_tuer (ER_NXF); - break; } -case FNC_WCHKF: /* wchk = read */ -case FNC_READF: /* read */ -DATA_XFER: - if ((uptr->flags & UNIT_ATT) == 0) { /* unattached? */ - set_tuer (ER_UNS); - break; } - if (fmt_test[GET_FMT (tutc)] == 0) { /* invalid format? */ - set_tuer (ER_FER); - break; } - if (uptr->UDENS == UD_UNK) uptr->UDENS = den; /* set dens */ - 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; + case FNC_WREOF: /* write tape mark */ + case FNC_ERASE: /* erase */ + if ((uptr->flags & UNIT_ATT) == 0) { /* unattached? */ + set_tuer (ER_UNS); + break; + } + if (sim_tape_wrp (uptr)) { /* write locked? */ + set_tuer (ER_NXF); + break; + } + if (fmt_test[GET_FMT (tutc)] == 0) { /* invalid format? */ + set_tuer (ER_FER); + break; + } + if (uptr->UDENS == UD_UNK) uptr->UDENS = den; /* set dens */ + uptr->USTAT = 0; + goto GO_XFER; -default: /* all others */ - set_tuer (ER_ILF); /* not supported */ - break; } /* end case function */ -tucs1 = tucs1 & ~CS1_GO; /* clear go */ -update_tucs (CS1_SC, drv); /* set intr */ + case FNC_WCHKR: /* wchk = read */ + case FNC_READR: /* read rev */ + if (tufs & FS_BOT) { /* beginning of tape? */ + set_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? */ + set_tuer (ER_NXF); + break; + } + case FNC_WCHKF: /* wchk = read */ + case FNC_READF: /* read */ + DATA_XFER: + if ((uptr->flags & UNIT_ATT) == 0) { /* unattached? */ + set_tuer (ER_UNS); + break; + } + if (fmt_test[GET_FMT (tutc)] == 0) { /* invalid format? */ + set_tuer (ER_FER); + break; + } + if (uptr->UDENS == UD_UNK) uptr->UDENS = den; /* set dens */ + 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 */ + set_tuer (ER_ILF); /* not supported */ + break; + } /* end case function */ + +tucs1 = tucs1 & ~CS1_GO; /* clear go */ +update_tucs (CS1_SC, drv); /* set intr */ return; } - + /* Unit service Complete movement or data transfer command @@ -709,66 +778,67 @@ 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; } +drv = (int32) (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; + } -fnc = 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 */ +fnc = 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 (fnc) { /* case on function */ - -/* Unit service - non-data transfer commands - set ATA when done */ +switch (fnc) { /* case on function */ -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, 0); /* map error */ - break; } - } - while (tufc != 0); - if (tufc) set_tuer (ER_FCE); - else tutc = tutc & ~TC_FCS; - tufs = tufs | FS_ATA; - break; +/* Non-data transfer commands - set ATA when done */ -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, 0); /* map error */ - break; } - } - while (tufc != 0); - if (tufc) set_tuer (ER_FCE); - else tutc = tutc & ~TC_FCS; - tufs = tufs | FS_ATA; - break; + 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, 0); /* map error */ + break; + } + } while (tufc != 0); + if (tufc) set_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, 0); /* map error */ - 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, 0); /* map error */ + break; + } + } while (tufc != 0); + if (tufc) set_tuer (ER_FCE); + else tutc = tutc & ~TC_FCS; + tufs = tufs | FS_ATA; + break; -case FNC_ERASE: - if (sim_tape_wrp (uptr)) /* write protected? */ - r = tu_map_err (uptr, MTSE_WRP, 0); /* map error */ - tufs = tufs | FS_ATA; - break; - -/* Unit service - data transfer commands + case FNC_WREOF: /* write end of file */ + if (st = sim_tape_wrtmk (uptr)) /* write tmk, err? */ + r = tu_map_err (uptr, st, 0); /* map error */ + tufs = tufs | FS_ATA; + break; + + case FNC_ERASE: + if (sim_tape_wrp (uptr)) /* write protected? */ + r = tu_map_err (uptr, MTSE_WRP, 0); /* map error */ + tufs = tufs | FS_ATA; + break; + +/* 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 @@ -781,90 +851,102 @@ case FNC_ERASE: 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, 1); /* 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 (fnc == FNC_READF) M[mpa10] = val; /* read? store */ - else if (M[mpa10] != val) { /* wchk, mismatch? */ - tucs2 = tucs2 | CS2_WCE; /* flag, stop */ - break; } - mpa10 = mpa10 + 1; } /* end for */ - tufc = tbc & 0177777; - tuwc = (tuwc + (i << 1)) & 0177777; - ba = ba + (i << 2); - if (tuwc) set_tuer (ER_FCE); /* short record? */ - break; + 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, 1); /* 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 (fnc == FNC_READF) M[mpa10] = val; /* read? store */ + else if (M[mpa10] != val) { /* wchk, mismatch? */ + tucs2 = tucs2 | CS2_WCE; /* flag, stop */ + break; + } + mpa10 = mpa10 + 1; + } /* end for */ + tufc = tbc & 0177777; + tuwc = (tuwc + (i << 1)) & 0177777; + ba = ba + (i << 2); + if (tuwc) set_tuer (ER_FCE); /* short record? */ + 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, 1); /* 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_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, 1); /* 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, 1); /* 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 (fnc == FNC_READR) M[mpa10] = val; /* read? store */ - else if (M[mpa10] != val) { /* wchk, mismatch? */ - tucs2 = tucs2 | CS2_WCE; /* flag, stop */ - break; } - mpa10 = mpa10 - 1; } /* end for */ - tufc = tbc & 0177777; - tuwc = (tuwc + (i << 1)) & 0177777; - ba = ba - (i << 2); - if (tuwc) set_tuer (ER_FCE); /* short record? */ - break; } /* end case */ + 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, 1); /* 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 (fnc == FNC_READR) M[mpa10] = val; /* read? store */ + else if (M[mpa10] != val) { /* wchk, mismatch? */ + tucs2 = tucs2 | CS2_WCE; /* flag, stop */ + break; + } + mpa10 = mpa10 - 1; + } /* end for */ + tufc = tbc & 0177777; + tuwc = (tuwc + (i << 1)) & 0177777; + ba = ba - (i << 2); + if (tuwc) set_tuer (ER_FCE); /* short record? */ + 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 */ -if (fnc >= FNC_XFER) update_tucs (CS1_DONE, drv); /* data xfer? */ -else update_tucs (CS1_SC, drv); /* no, set attn */ +tuba = ba & 0177777; /* update mem addr */ +tucs1 = tucs1 & ~CS1_GO; /* clear go */ +if (fnc >= FNC_XFER) update_tucs (CS1_DONE, drv); /* data xfer? */ +else update_tucs (CS1_SC, drv); /* no, set attn */ if (DEBUG_PRS (tu_dev)) fprintf (sim_deb, - ">>TU%d DONE: fnc=%s, cs1=%06o, cs2=%06o, ba=%06o, wc=%06o, fc=%06o, fs=%06o, er=%06o, pos=%d\n", - drv, tu_fname[fnc], tucs1, tucs2, tuba, tuwc, tufc, tufs, tuer, uptr->pos); + ">>TU%d DONE: fnc=%s, cs1=%06o, cs2=%06o, ba=%06o, wc=%06o, fc=%06o, fs=%06o, er=%06o, pos=%d\n", + drv, tu_fname[fnc], tucs1, tucs2, tuba, tuwc, tufc, tufs, tuer, uptr->pos); return SCPE_OK; } - + /* Formatter error */ void set_tuer (int32 flag) @@ -887,23 +969,25 @@ 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; } +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; + int_req = int_req | INT_TU; else int_req = int_req & ~INT_TU; if ((tucs1 & CS1_DONE) && tufs && !act) tufs = tufs | FS_RDY; return; @@ -913,9 +997,9 @@ return; int32 tu_inta (void) { -tucs1 = tucs1 & ~CS1_IE; /* clear int enable */ -tuiff = 0; /* clear CSTB INTR */ -return VEC_TU; /* acknowledge */ +tucs1 = tucs1 & ~CS1_IE; /* clear int enable */ +tuiff = 0; /* clear CSTB INTR */ +return VEC_TU; /* acknowledge */ } /* Map tape error status */ @@ -923,42 +1007,52 @@ return VEC_TU; /* acknowledge */ t_stat tu_map_err (UNIT *uptr, t_stat st, t_bool qdt) { switch (st) { -case MTSE_FMT: /* illegal fmt */ -case MTSE_UNATT: /* not attached */ - set_tuer (ER_NXF); /* can't execute */ - if (qdt) tucs1 = tucs1 | CS1_TRE; /* data xfr? set TRE */ -case MTSE_OK: /* no error */ - return SCPE_IERR; -case MTSE_TMK: /* end of file */ - set_tuer (ER_FCE); /* also sets FCE */ - tufs = tufs | FS_TMK; - break; -case MTSE_IOERR: /* IO error */ - set_tuer (ER_VPE); /* flag error */ - if (qdt) tucs1 = tucs1 | CS1_TRE; /* data xfr? set TRE */ - if (tu_stopioe) return SCPE_IOERR; - break; -case MTSE_INVRL: /* invalid rec lnt */ - set_tuer (ER_VPE); /* flag error */ - if (qdt) tucs1 = tucs1 | CS1_TRE; /* data xfr? set TRE */ - return SCPE_MTRLNT; -case MTSE_RECE: /* record in error */ - set_tuer (ER_CRC); /* set crc err */ - if (qdt) tucs1 = tucs1 | CS1_TRE; /* data xfr? set TRE */ - break; -case MTSE_EOM: /* end of medium */ - set_tuer (ER_OPI); /* incomplete */ - if (qdt) tucs1 = tucs1 | CS1_TRE; /* data xfr? set TRE */ - break; -case MTSE_BOT: /* reverse into BOT */ - break; -case MTSE_WRP: /* write protect */ - set_tuer (ER_NXF); /* can't execute */ - if (qdt) tucs1 = tucs1 | CS1_TRE; /* data xfr? set TRE */ - break; } + + case MTSE_FMT: /* illegal fmt */ + case MTSE_UNATT: /* not attached */ + set_tuer (ER_NXF); /* can't execute */ + if (qdt) tucs1 = tucs1 | CS1_TRE; /* data xfr? set TRE */ + case MTSE_OK: /* no error */ + return SCPE_IERR; + + case MTSE_TMK: /* end of file */ + set_tuer (ER_FCE); /* also sets FCE */ + tufs = tufs | FS_TMK; + break; + + case MTSE_IOERR: /* IO error */ + set_tuer (ER_VPE); /* flag error */ + if (qdt) tucs1 = tucs1 | CS1_TRE; /* data xfr? set TRE */ + if (tu_stopioe) return SCPE_IOERR; + break; + + case MTSE_INVRL: /* invalid rec lnt */ + set_tuer (ER_VPE); /* flag error */ + if (qdt) tucs1 = tucs1 | CS1_TRE; /* data xfr? set TRE */ + return SCPE_MTRLNT; + + case MTSE_RECE: /* record in error */ + set_tuer (ER_CRC); /* set crc err */ + if (qdt) tucs1 = tucs1 | CS1_TRE; /* data xfr? set TRE */ + break; + + case MTSE_EOM: /* end of medium */ + set_tuer (ER_OPI); /* incomplete */ + if (qdt) tucs1 = tucs1 | CS1_TRE; /* data xfr? set TRE */ + break; + + case MTSE_BOT: /* reverse into BOT */ + break; + + case MTSE_WRP: /* write protect */ + set_tuer (ER_NXF); /* can't execute */ + if (qdt) tucs1 = tucs1 | CS1_TRE; /* data xfr? set TRE */ + break; + } + return SCPE_OK; } - + /* Reset routine */ t_stat tu_reset (DEVICE *dptr) @@ -973,16 +1067,17 @@ tuwc = 0; tufc = 0; tuer = 0; tufs = FS_FPR | FS_RDY; -if (sim_switches & SWMASK ('P')) tutc = 0; /* powerup? clr TC */ -else tutc = tutc & ~TC_FCS; /* no, clr */ -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 (sim_switches & SWMASK ('P')) tutc = 0; /* powerup? clr TC */ +else tutc = tutc & ~TC_FCS; /* no, clr */ +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 = (uint8 *) calloc (MT_MAXFR + 4, sizeof (uint8)); if (xbuf == NULL) return SCPE_MEM; return SCPE_OK; } @@ -996,12 +1091,12 @@ 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 */ +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; } @@ -1011,98 +1106,100 @@ t_stat tu_detach (UNIT* uptr) { int32 drv = uptr - tu_dev.units; -if (!(uptr->flags & UNIT_ATT)) return SCPE_OK; /* attached? */ -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 */ +if (!(uptr->flags & UNIT_ATT)) return SCPE_OK; /* attached? */ +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_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 */ -}; + 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 */ -}; + 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; @@ -1112,7 +1209,7 @@ 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]; + 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 index e22546ae..88ec0b08 100644 --- a/PDP10/pdp10_xtnd.c +++ b/PDP10/pdp10_xtnd.c @@ -1,6 +1,6 @@ /* pdp10_xtnd.c: PDP-10 extended instruction simulator - Copyright (c) 1993-2004, Robert M Supnik + Copyright (c) 1993-2005, 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"), @@ -19,28 +19,29 @@ 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 + 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 + 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 + + 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 @@ -56,87 +57,88 @@ 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 + + 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 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 +#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 */ +#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)) +#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 */ +#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 +#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 */ +#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; @@ -175,8 +177,9 @@ static const d10 pwrs10[23][2] = { 29103830, 15693250560, 291038304, 19493552128, 2910383045, 23136829440, - 29103830456, 25209864192 }; - + 29103830456, 25209864192 + }; + int xtend (int32 ac, int32 ea, int32 pflgs) { d10 b1, b2, ppi; @@ -188,309 +191,366 @@ 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 */ +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 */ +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 + 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; - + 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 + 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 */ + 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; - + 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 + 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; - + 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 + 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; } + 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; + } /* end case xop */ + + 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; - 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 + 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 */ + 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 */ @@ -499,13 +559,14 @@ d10 incbp (d10 bp) { int32 p, s; -p = GET_P (bp); /* get P and 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 */ +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; } @@ -517,13 +578,13 @@ 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 */ +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 */ +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; } @@ -535,15 +596,15 @@ 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 */ +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 */ +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 */ +wd = (wd & ~mask) | (val & mask); /* insert byte */ Write (ba, wd & DMASK, MM_XDST); return; } @@ -551,13 +612,13 @@ 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 + 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 + xby = >= 0, translated byte + < 0, terminate translation */ d10 xlate (d10 by, a10 tblad, d10 *xflgs, int32 prv) @@ -568,40 +629,50 @@ d10 tblent; ea = (tblad + ((int32) by >> 1)) & AMASK; tblent = ((Read (ea, prv) >> ((by & 1)? 0: 18)) & RMASK); -tcode = XT_GETCODE (tblent); /* get xlate code */ +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 */ + + 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 */ + return -1; } /* Fill out the destination string Arguments: - fill = fill - ac = 2 word AC block (length, byte pointer) - cnt = fill count - pflgs = PXCT flags + 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) @@ -610,18 +681,19 @@ 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; + 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 + 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 @@ -633,10 +705,11 @@ 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 */ - } + 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 index b817f355..dfd04d94 100644 --- a/PDP11/pdp11_cis.c +++ b/PDP11/pdp11_cis.c @@ -1,6 +1,6 @@ /* pdp11_cis.c: PDP-11 CIS optional instruction set simulator - Copyright (c) 1993-2004, Robert M Supnik + Copyright (c) 1993-2005, 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"), @@ -19,57 +19,57 @@ 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 + 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). - 16-Sep-04 RMS Fixed bug in CMPP/N of negative strings - 17-Oct-02 RMS Fixed compiler warning (found by Hans Pufal) - 08-Oct-02 RMS Fixed macro definitions + 16-Sep-04 RMS Fixed bug in CMPP/N of negative strings + 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 + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ 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 + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ 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 + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ 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 + | length in bytes | char string + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ descriptor | starting byte address | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - | |str type| | length | decimal string - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ descriptor + | |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 + <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). @@ -78,87 +78,86 @@ 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 */ +#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 */ +#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 */ +#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) +#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) +#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] +#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) +#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 */ +#define DSTRLNT 4 +#define DSTRMAX (DSTRLNT - 1) +#define MAXDVAL 429496730 /* 2^32 / 10 */ -struct dstr { - uint32 sign; - uint32 val[DSTRLNT]; }; - -typedef struct dstr DSTR; +typedef struct { + uint32 sign; + uint32 val[DSTRLNT]; + } DSTR; static DSTR Dstr0 = { 0, 0, 0, 0, 0 }; @@ -181,134 +180,134 @@ uint32 NibbleRshift (DSTR *dsrc, int32 sc, uint32 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 */ -}; + 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 -}; + 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' -}; + '{', '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) @@ -316,599 +315,639 @@ 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 */ +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 */ - +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) + 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 + NZVC = set from src.lnt - dst.lnt Registers (MOVC, MOVTC only) - R0 = max (0, src.len - dst.len) - R1:R3 = 0 - R4:R5 = unchanged + 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. + 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; - + 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 + A1LNT, A1ADR = source string descriptor + A2LNT, A2ADR = dest string descriptor + A3LNT<7:0> = fill character Condition codes: - NZVC = set from src.lnt - dst.lnt + NZVC = set from src.lnt - dst.lnt Registers (MOVRC only) - R0 = max (0, src.len - dst.len) - R1:R3 = 0 - R4:R5 = unchanged + 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; + 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; - + 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 + R0, R1 = source string descriptor + A1LNT<7:0> = match character Condition codes: - NZ = set from R0 - VC = 0 + NZ = set from R0 + VC = 0 Registers: - R0:R1 = substring descriptor where operation terminated + 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; + 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 + R0, R1 = source string descriptor + A1LNT<7:0> = mask + A1ADR = table address Condition codes: - NZ = set from R0 - VC = 0 + NZ = set from R0 + VC = 0 Registers: - R0:R1 = substring descriptor where operation terminated + 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; - + 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 + 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 + 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 + 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; - + 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 + R0, R1 = source string descriptor + A1LNT, A1ADR = substring descriptor Condition codes: - NZ = set from R0 - VC = 0 + NZ = set from R0 + VC = 0 Registers: - R0:R1 = source substring descriptor for match + 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" + - 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; - + 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 + A1LNT, A1ADR = source1 string descriptor + A2LNT, A2ADR = source2 string descriptor + A3LNT, A3ADR = destination string descriptor Condition codes: - NZV = set from result - C = 0 + NZV = set from result + C = 0 Registers (ADDN, ADDP, SUBN, SUBP only): - R0:R3 = 0 + 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; - + 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 + A1LNT, A1ADR = source1 string descriptor + A2LNT, A2ADR = source2 string descriptor + A3LNT, A3ADR = destination string descriptor Condition codes: - NZV = set from result - C = 0 + NZV = set from result + C = 0 Registers (MULP only): - R0:R3 = 0 + 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; - + 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 + 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 + NZV = set from result + C = set if divide by zero Registers (DIVP only): - R0:R3 = 0 + 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; - + 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 */ + } /* end 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 + A1LNT, A1ADR = source1 string descriptor + A2LNT, A2ADR = source2 string descriptor Condition codes: - NZ = set from comparison - VC = 0 + NZ = set from comparison + VC = 0 Registers (CMPN, CMPP only): - R0:R3 = 0 + 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 = (src1.sign? 0: 1); - else if (t > 0) N = (src1.sign? 1: 0); - else Z = 1; } - if ((op & INLINE) == 0) /* if reg, clr reg */ - R[0] = R[1] = R[2] = R[3] = 0; - return; - + 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 = (src1.sign? 0: 1); + else if (t > 0) N = (src1.sign? 1: 0); + else 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 + 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 + NZV = set from result + C = 0 Registers (ASHN, ASHP only): - R0:R1, R4 = 0 + 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; - + 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 + A1LNT, A1ADR = source string descriptor + A2LNT, A2ADR = destination string descriptor Condition codes: - NZV = set from result - C = 0 + NZV = set from result + C = 0 - Registers (CVTPN only): - R0:R1 = 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; + 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 + A1LNT, A1ADR = source string descriptor + A2LNT, A2ADR = destination string descriptor Condition codes: - NZV = set from result - C = 0 + NZV = set from result + C = 0 - Registers (CVTNP only): - R0:R1 = 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; - + 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) + A1LNT, A1ADR = source string descriptor + A2LNT = destination address (inline only) Condition codes: - NZV = set from result - C = source < 0 and result != 0 + NZV = set from result + C = source < 0 and result != 0 Registers (CVTNL, CVTPL only): - R0:R1 = 0 - R2:R3 = result + 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; - + 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 + 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 + NZV = set from result + C = 0 Registers (CVTLN, CVTLP only) - R2:R3 = 0 + 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; } + 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; + } /* end case */ return; -} /* end cis */ - +} /* end cis */ + /* Get decimal string Arguments: - dscr = decimal string descriptor - src = decimal string structure - flag = numeric/packed flag + 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. @@ -931,56 +970,57 @@ 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 */ +*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 + 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) + (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 + - 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 @@ -991,57 +1031,59 @@ 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 }; + 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 */ +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 */ +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 */ +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 */ + 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 + 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 @@ -1049,11 +1091,11 @@ return; carry is fixed; each parenthesized item is a 4b digit. Assume we are adding: - (a)(b) I - + (x)(y) J + (a)(b) I + + (x)(y) J First compute I^J: - (a^x)(b^y) TMP + (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 @@ -1061,7 +1103,7 @@ return; 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 + (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. @@ -1077,25 +1119,26 @@ int32 AddDstr (DSTR *s1, DSTR *s2, DSTR *ds, int32 cy) int32 i; uint32 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 */ +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 + s1 = source1 decimal string + s2 = source2 decimal string + ds = destination decimal string + Outputs: s2 - s1 in ds Note: the routine assumes that s1 <= s2 @@ -1107,16 +1150,16 @@ 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 */ +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 < + s1 = source1 decimal string + s2 = source2 decimal string + Output = 1 if >, 0 if =, -1 if < */ int32 CmpDstr (DSTR *s1, DSTR *s2) @@ -1124,15 +1167,16 @@ 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; } + 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 + dsrc = decimal string structure Returns the non-zero length of the string, in int32 units If the string is zero, the sign is cleared */ @@ -1149,8 +1193,8 @@ return 0; /* Get exact length of decimal string Arguments: - dsrc = decimal string structure - nz = result from TestDstr + dsrc = decimal string structure + nz = result from TestDstr */ int32 LntDstr (DSTR *dsrc, int32 nz) @@ -1158,18 +1202,19 @@ int32 LntDstr (DSTR *dsrc, int32 nz) int32 i; for (i = 7; i > 0; i--) { - if ((dsrc->val[nz - 1] >> (i * 4)) & 0xF) break; } + 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 + 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 + guarantees that the largest multiple won't overflow Also note that mtable[0] is not filled in */ @@ -1181,12 +1226,12 @@ 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 + dsrc = decimal string structure + sc = shift count */ void WordRshift (DSTR *dsrc, int32 sc) @@ -1194,17 +1239,19 @@ 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; } } + 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 + dsrc = decimal string structure + sc = shift count */ int32 WordLshift (DSTR *dsrc, int32 sc) @@ -1213,19 +1260,21 @@ 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; } } + 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 + dsrc = decimal string structure + sc = shift count + cin = carry in */ uint32 NibbleRshift (DSTR *dsrc, int32 sc, uint32 cin) @@ -1233,22 +1282,24 @@ uint32 NibbleRshift (DSTR *dsrc, int32 sc, uint32 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; } + 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 + dsrc = decimal string structure + sc = shift count + cin = carry in */ uint32 NibbleLshift (DSTR *dsrc, int32 sc, uint32 cin) @@ -1256,12 +1307,14 @@ uint32 NibbleLshift (DSTR *dsrc, int32 sc, uint32 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; } + 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 index 808edf15..9acad12a 100644 --- a/PDP11/pdp11_cpu.c +++ b/PDP11/pdp11_cpu.c @@ -19,157 +19,157 @@ 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 + 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 + cpu PDP-11 CPU - 19-Jan-05 RMS Fixed bug(s) in RESET for 11/70 (reported by Tim Chapman) - 22-Dec-04 RMS Fixed WAIT to work in all modes (from John Dundas) - 02-Oct-04 RMS Added model emulation - 25-Jan-04 RMS Removed local debug logging support - 29-Dec-03 RMS Formalized 18b Qbus support - 21-Dec-03 RMS Added autoconfiguration controls - 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 + 16-Aug-05 RMS Fixed C++ declaration and cast problems + 19-May-05 RMS Replaced WAIT clock queue check with API call + 19-Jan-05 RMS Fixed bug(s) in RESET for 11/70 (reported by Tim Chapman) + 22-Dec-04 RMS Fixed WAIT to work in all modes (from John Dundas) + 02-Oct-04 RMS Added model emulation + 25-Jan-04 RMS Removed local debug logging support + 29-Dec-03 RMS Formalized 18b Qbus support + 21-Dec-03 RMS Added autoconfiguration controls + 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 - <8> = FPD first part done (CIS) - <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: + 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 + <8> = FPD first part done (CIS) + <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 - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ double operand - | opcode | source spec | dest spec | 010000:067777 - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ 110000:167777 + The PDP-11 has many instruction formats: - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ register + operand - | opcode | src reg| dest spec | 004000:004777 - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ 070000:077777 + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ double operand + | opcode | source spec | dest spec | 010000:067777 + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ 110000:167777 - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ single operand - | opcode | dest spec | 000100:000177 - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ 000300:000377 - 005000:007777 - 105000:107777 + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ register + operand + | opcode | src reg| dest spec | 004000:004777 + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ 070000:077777 - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ single register - | opcode |dest reg| 000200:000207 - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ 000230:000237 + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ single operand + | opcode | dest spec | 000100:000177 + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ 000300:000377 + 005000:007777 + 105000:107777 - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ no operand - | opcode | 000000:000007 + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ single register + | opcode |dest reg| 000200:000207 + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ 000230:000237 + + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ no operand + | opcode | 000000:000007 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ branch - | opcode | branch displacement | 000400:003477 - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ 100000:103477 + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ branch + | opcode | branch displacement | 000400:003477 + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ 100000:103477 - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ EMT/TRAP - | opcode | trap code | 104000:104777 + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ EMT/TRAP + | opcode | trap code | 104000:104777 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ cond code operator - | opcode | immediate | 000240:000277 + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ 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]] + 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 + 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. @@ -202,88 +202,87 @@ 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 + pdp11_defs.h add device address and interrupt definitions + pdp11_sys.c add to sim_devices table entry */ - + /* Definitions */ #include "pdp11_defs.h" #include "pdp11_cpumod.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_MSIZE (UNIT_V_UF + 0) /* dummy */ -#define UNIT_MSIZE (1u << UNIT_V_MSIZE) +#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_MSIZE (UNIT_V_UF + 0) /* dummy */ +#define UNIT_MSIZE (1u << UNIT_V_MSIZE) /* 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 fpd = 0; /* first part done */ - 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 STKLIM = 0; /* stack limit */ -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 cpu_bme = 0; /* bus map enable */ -int32 cpu_astop = 0; /* address stop */ -int32 isenable = 0, dsenable = 0; /* i, d space flags */ -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 autcon_enb = 1; /* autoconfig enable */ -uint32 cpu_model = MOD_1173; /* CPU model */ -uint32 cpu_type = 1u << MOD_1173; /* model as bit mask */ -uint32 cpu_opt = SOP_1173; /* CPU options */ -uint16 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; /* abort handler */ -int32 dsmask[4] = { MMR3_KDS, MMR3_SDS, 0, MMR3_UDS }; /* dspace enables */ +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 fpd = 0; /* first part done */ + 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 STKLIM = 0; /* stack limit */ +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 cpu_bme = 0; /* bus map enable */ +int32 cpu_astop = 0; /* address stop */ +int32 isenable = 0, dsenable = 0; /* i, d space flags */ +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 autcon_enb = 1; /* autoconfig enable */ +uint32 cpu_model = MOD_1173; /* CPU model */ +uint32 cpu_type = 1u << MOD_1173; /* model as bit mask */ +uint32 cpu_opt = SOP_1173; /* CPU options */ +uint16 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; /* abort handler */ +int32 dsmask[4] = { MMR3_KDS, MMR3_SDS, 0, MMR3_UDS }; /* dspace enables */ extern int32 CPUERR, MAINT; 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 int32 sim_brk_types, sim_brk_dflt, sim_brk_summ; /* breakpoint info */ extern DEVICE *sim_devices[]; extern CPUTAB cpu_tab[]; - + /* Function declarations */ t_stat cpu_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw); @@ -327,307 +326,312 @@ 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_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 + }; -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 }; - /* CPU data structures - cpu_dev CPU device descriptor - cpu_unit CPU unit descriptor - cpu_reg CPU register list - cpu_mod CPU modifier list + 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) }, - { FLDATA (FPD, PSW, PSW_V_FPD) }, - { 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 (PIRQ, PIRQ, 16) }, - { ORDATA (STKLIM, STKLIM, 16) }, - { 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 (IREQ, int_req, 8, 32, IPL_HLVL), REG_RO }, - { ORDATA (TRAPS, trap_req, TRAP_V_MAX) }, - { 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) }, - { FLDATA (AUTOCON, autcon_enb, 0), REG_HRO }, - { 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 (MODEL, cpu_model, 16), REG_HRO }, - { ORDATA (OPTIONS, cpu_opt, 32), REG_HRO }, - { NULL} }; + { 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) }, + { FLDATA (FPD, PSW, PSW_V_FPD) }, + { 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 (PIRQ, PIRQ, 16) }, + { ORDATA (STKLIM, STKLIM, 16) }, + { 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 (IREQ, int_req, 8, 32, IPL_HLVL), REG_RO }, + { ORDATA (TRAPS, trap_req, TRAP_V_MAX) }, + { 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) }, + { FLDATA (AUTOCON, autcon_enb, 0), REG_HRO }, + { 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 (MODEL, cpu_model, 16), REG_HRO }, + { ORDATA (OPTIONS, cpu_opt, 32), REG_HRO }, + { NULL} + }; MTAB cpu_mod[] = { - { MTAB_XTD|MTAB_VDV, 0, "TYPE", NULL, - NULL, &cpu_show_model }, - { MTAB_XTD|MTAB_VDV, MOD_1103, NULL, "11/03", &cpu_set_model }, - { MTAB_XTD|MTAB_VDV, MOD_1104, NULL, "11/04", &cpu_set_model }, - { MTAB_XTD|MTAB_VDV, MOD_1105, NULL, "11/05", &cpu_set_model }, - { MTAB_XTD|MTAB_VDV, MOD_1120, NULL, "11/20", &cpu_set_model }, - { MTAB_XTD|MTAB_VDV, MOD_1123, NULL, "11/23", &cpu_set_model }, - { MTAB_XTD|MTAB_VDV, MOD_1123P, NULL, "11/23+", &cpu_set_model }, - { MTAB_XTD|MTAB_VDV, MOD_1124, NULL, "11/24", &cpu_set_model }, - { MTAB_XTD|MTAB_VDV, MOD_1134, NULL, "11/34", &cpu_set_model }, - { MTAB_XTD|MTAB_VDV, MOD_1140, NULL, "11/40", &cpu_set_model }, - { MTAB_XTD|MTAB_VDV, MOD_1144, NULL, "11/44", &cpu_set_model }, - { MTAB_XTD|MTAB_VDV, MOD_1145, NULL, "11/45", &cpu_set_model }, - { MTAB_XTD|MTAB_VDV, MOD_1153, NULL, "11/53", &cpu_set_model }, - { MTAB_XTD|MTAB_VDV, MOD_1160, NULL, "11/60", &cpu_set_model }, - { MTAB_XTD|MTAB_VDV, MOD_1170, NULL, "11/70", &cpu_set_model }, - { MTAB_XTD|MTAB_VDV, MOD_1173, NULL, "11/73", &cpu_set_model }, - { MTAB_XTD|MTAB_VDV, MOD_1173B, NULL, "11/73B", &cpu_set_model }, - { MTAB_XTD|MTAB_VDV, MOD_1183, NULL, "11/83", &cpu_set_model }, - { MTAB_XTD|MTAB_VDV, MOD_1184, NULL, "11/84", &cpu_set_model }, - { MTAB_XTD|MTAB_VDV, MOD_1193, NULL, "11/93", &cpu_set_model }, - { MTAB_XTD|MTAB_VDV, MOD_1194, NULL, "11/94", &cpu_set_model }, - { MTAB_XTD|MTAB_VDV, MOD_1173, NULL, "Q22", &cpu_set_model }, - { MTAB_XTD|MTAB_VDV, MOD_1184, NULL, "URH11", &cpu_set_model }, - { MTAB_XTD|MTAB_VDV, MOD_1170, NULL, "URH70", &cpu_set_model }, - { MTAB_XTD|MTAB_VDV, MOD_1145, NULL, "U18", &cpu_set_model }, - { MTAB_XTD|MTAB_VDV, OPT_EIS, NULL, "EIS", &cpu_set_opt }, - { MTAB_XTD|MTAB_VDV, OPT_EIS, NULL, "NOEIS", &cpu_clr_opt }, - { MTAB_XTD|MTAB_VDV, OPT_FIS, NULL, "FIS", &cpu_set_opt }, - { MTAB_XTD|MTAB_VDV, OPT_FIS, NULL, "NOFIS", &cpu_clr_opt }, - { MTAB_XTD|MTAB_VDV, OPT_FPP, NULL, "FPP", &cpu_set_opt }, - { MTAB_XTD|MTAB_VDV, OPT_FPP, NULL, "NOFPP", &cpu_clr_opt }, - { MTAB_XTD|MTAB_VDV, OPT_CIS, NULL, "CIS", &cpu_set_opt }, - { MTAB_XTD|MTAB_VDV, OPT_CIS, NULL, "NOCIS", &cpu_clr_opt }, - { MTAB_XTD|MTAB_VDV, OPT_MMU, NULL, "MMU", &cpu_set_opt }, - { MTAB_XTD|MTAB_VDV, OPT_MMU, NULL, "NOMMU", &cpu_clr_opt }, - { 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 }, - { MTAB_XTD|MTAB_VDV, 1, "AUTOCONFIG", "AUTOCONFIG", - &set_autocon, &show_autocon }, - { MTAB_XTD|MTAB_VDV, 0, NULL, "NOAUTOCONFIG", - &set_autocon, NULL }, - { 0 } }; + { MTAB_XTD|MTAB_VDV, 0, "TYPE", NULL, + NULL, &cpu_show_model }, + { MTAB_XTD|MTAB_VDV, MOD_1103, NULL, "11/03", &cpu_set_model }, + { MTAB_XTD|MTAB_VDV, MOD_1104, NULL, "11/04", &cpu_set_model }, + { MTAB_XTD|MTAB_VDV, MOD_1105, NULL, "11/05", &cpu_set_model }, + { MTAB_XTD|MTAB_VDV, MOD_1120, NULL, "11/20", &cpu_set_model }, + { MTAB_XTD|MTAB_VDV, MOD_1123, NULL, "11/23", &cpu_set_model }, + { MTAB_XTD|MTAB_VDV, MOD_1123P, NULL, "11/23+", &cpu_set_model }, + { MTAB_XTD|MTAB_VDV, MOD_1124, NULL, "11/24", &cpu_set_model }, + { MTAB_XTD|MTAB_VDV, MOD_1134, NULL, "11/34", &cpu_set_model }, + { MTAB_XTD|MTAB_VDV, MOD_1140, NULL, "11/40", &cpu_set_model }, + { MTAB_XTD|MTAB_VDV, MOD_1144, NULL, "11/44", &cpu_set_model }, + { MTAB_XTD|MTAB_VDV, MOD_1145, NULL, "11/45", &cpu_set_model }, + { MTAB_XTD|MTAB_VDV, MOD_1153, NULL, "11/53", &cpu_set_model }, + { MTAB_XTD|MTAB_VDV, MOD_1160, NULL, "11/60", &cpu_set_model }, + { MTAB_XTD|MTAB_VDV, MOD_1170, NULL, "11/70", &cpu_set_model }, + { MTAB_XTD|MTAB_VDV, MOD_1173, NULL, "11/73", &cpu_set_model }, + { MTAB_XTD|MTAB_VDV, MOD_1173B, NULL, "11/73B", &cpu_set_model }, + { MTAB_XTD|MTAB_VDV, MOD_1183, NULL, "11/83", &cpu_set_model }, + { MTAB_XTD|MTAB_VDV, MOD_1184, NULL, "11/84", &cpu_set_model }, + { MTAB_XTD|MTAB_VDV, MOD_1193, NULL, "11/93", &cpu_set_model }, + { MTAB_XTD|MTAB_VDV, MOD_1194, NULL, "11/94", &cpu_set_model }, + { MTAB_XTD|MTAB_VDV, MOD_1173, NULL, "Q22", &cpu_set_model }, + { MTAB_XTD|MTAB_VDV, MOD_1184, NULL, "URH11", &cpu_set_model }, + { MTAB_XTD|MTAB_VDV, MOD_1170, NULL, "URH70", &cpu_set_model }, + { MTAB_XTD|MTAB_VDV, MOD_1145, NULL, "U18", &cpu_set_model }, + { MTAB_XTD|MTAB_VDV, OPT_EIS, NULL, "EIS", &cpu_set_opt }, + { MTAB_XTD|MTAB_VDV, OPT_EIS, NULL, "NOEIS", &cpu_clr_opt }, + { MTAB_XTD|MTAB_VDV, OPT_FIS, NULL, "FIS", &cpu_set_opt }, + { MTAB_XTD|MTAB_VDV, OPT_FIS, NULL, "NOFIS", &cpu_clr_opt }, + { MTAB_XTD|MTAB_VDV, OPT_FPP, NULL, "FPP", &cpu_set_opt }, + { MTAB_XTD|MTAB_VDV, OPT_FPP, NULL, "NOFPP", &cpu_clr_opt }, + { MTAB_XTD|MTAB_VDV, OPT_CIS, NULL, "CIS", &cpu_set_opt }, + { MTAB_XTD|MTAB_VDV, OPT_CIS, NULL, "NOCIS", &cpu_clr_opt }, + { MTAB_XTD|MTAB_VDV, OPT_MMU, NULL, "MMU", &cpu_set_opt }, + { MTAB_XTD|MTAB_VDV, OPT_MMU, NULL, "NOMMU", &cpu_clr_opt }, + { 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 }, + { MTAB_XTD|MTAB_VDV, 1, "AUTOCONFIG", "AUTOCONFIG", + &set_autocon, &show_autocon }, + { MTAB_XTD|MTAB_VDV, 0, NULL, "NOAUTOCONFIG", + &set_autocon, NULL }, + { 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, 0, - NULL, &cpu_set_size, NULL }; - + "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, 0, + NULL, &cpu_set_size, NULL + }; + t_stat sim_instr (void) { int abortval, i; -volatile int32 trapea; /* used by setjmp */ +volatile int32 trapea; /* used by setjmp */ t_stat reason; /* 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 + 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 */ -reason = build_dib_tab (); /* build, chk dib_tab */ +reason = build_dib_tab (); /* build, chk dib_tab */ if (reason != SCPE_OK) return reason; -cpu_type = 1u << cpu_model; /* reset type mask */ -cpu_bme = (MMR3 & MMR3_BME) && (cpu_opt & OPT_UBM); /* map enabled? */ +cpu_type = 1u << cpu_model; /* reset type mask */ +cpu_bme = (MMR3 & MMR3_BME) && (cpu_opt & OPT_UBM); /* map enabled? */ PC = saved_PC; -put_PSW (PSW, 0); /* set PSW, call calc_xs */ +put_PSW (PSW, 0); /* set PSW, call calc_xs */ for (i = 0; i < 6; i++) R[i] = REGFILE[i][rs]; SP = STACKFILE[cm]; isenable = calc_is (cm); dsenable = calc_ds (cm); -put_PIRQ (PIRQ); /* rewrite PIRQ */ -STKLIM = STKLIM & STKLIM_RW; /* clean up STKLIM */ -MMR0 = MMR0 | MMR0_IC; /* usually on */ +put_PIRQ (PIRQ); /* rewrite PIRQ */ +STKLIM = STKLIM & STKLIM_RW; /* clean up STKLIM */ +MMR0 = MMR0 | MMR0_IC; /* usually on */ -trap_req = calc_ints (ipl, trap_req); /* upd int req */ +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 */ - +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 @@ -645,17 +649,19 @@ sim_rtcn_init (pclk_unit.wait, TMR_PCLK); /* init prog clock */ after setjmp, must be volatile or global. */ -abortval = setjmp (save_env); /* set abort hdlr */ +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) && /* stack push abort? */ - (CPUT (STOP_STKA) || 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; } } + trap_req = trap_req | abortval; /* or in trap flag */ + if ((trapea > 0) && stop_vecabort) reason = STOP_VECABORT; + if ((trapea < 0) && /* stack push abort? */ + (CPUT (STOP_STKA) || 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 @@ -665,43 +671,44 @@ if (abortval != 0) { while (reason == 0) { -int32 IR, srcspec, srcreg, dstspec, dstreg; -int32 src, src2, dst, ea; -int32 i, t, sign, oldrs, trapnum; + 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 (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 (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 */ -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 @@ -713,458 +720,507 @@ if (trap_req) { /* check traps, ints */ 7. If not stack overflow, check for stack overflow */ - wait_state = 0; /* exit wait state */ - STACKFILE[cm] = SP; - PSW = get_PSW (); /* assemble PSW */ - oldrs = rs; - if (CPUT (HAS_MMTR)) { /* 45,70? */ - if (update_MM) MMR2 = trapea; /* save vector */ - MMR0 = MMR0 & ~MMR0_IC; } /* clear IC */ - src = ReadW (trapea | calc_ds (MD_KER)); /* new PC */ - src2 = ReadW ((trapea + 2) | calc_ds (MD_KER)); /* new PSW */ - t = (src2 >> PSW_V_CM) & 03; /* new cm */ - 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 */ - src2 = (src2 & ~PSW_PM) | (cm << PSW_V_PM); /* insert prv mode */ - put_PSW (src2, 0); /* call calc_is,ds */ - 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 */ - isenable = calc_is (cm); - dsenable = calc_ds (cm); - trap_req = calc_ints (ipl, trap_req); - JMP_PC (src); - if ((cm == MD_KER) && (SP < (STKLIM + STKL_Y)) && - (trapnum != TRAP_V_RED) && (trapnum != TRAP_V_YEL)) - set_stack_trap (SP); - MMR0 = MMR0 | MMR0_IC; /* back to instr */ - continue; } /* end if traps */ - + wait_state = 0; /* exit wait state */ + STACKFILE[cm] = SP; + PSW = get_PSW (); /* assemble PSW */ + oldrs = rs; + if (CPUT (HAS_MMTR)) { /* 45,70? */ + if (update_MM) MMR2 = trapea; /* save vector */ + MMR0 = MMR0 & ~MMR0_IC; /* clear IC */ + } + src = ReadW (trapea | calc_ds (MD_KER)); /* new PC */ + src2 = ReadW ((trapea + 2) | calc_ds (MD_KER)); /* new PSW */ + t = (src2 >> PSW_V_CM) & 03; /* new cm */ + 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 */ + src2 = (src2 & ~PSW_PM) | (cm << PSW_V_PM); /* insert prv mode */ + put_PSW (src2, 0); /* call calc_is,ds */ + 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 */ + isenable = calc_is (cm); + dsenable = calc_ds (cm); + trap_req = calc_ints (ipl, trap_req); + JMP_PC (src); + if ((cm == MD_KER) && (SP < (STKLIM + STKL_Y)) && + (trapnum != TRAP_V_RED) && (trapnum != TRAP_V_YEL)) + set_stack_trap (SP); + MMR0 = MMR0 | MMR0_IC; /* back to instr */ + 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 (tbit) setTRAP (TRAP_TRC); + if (wait_state) { /* wait state? */ + if (sim_qcount () != 0) 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 (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 = ReadE (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> */ -if (update_MM) { /* if mm not frozen */ - MMR1 = 0; - MMR2 = PC; } -IR = ReadE (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) && - (!CPUT (CPUT_J) || ((MAINT & MAINT_HTRAP) == 0))) - reason = STOP_HALT; - else if (CPUT (HAS_HALT4)) { /* priv trap? */ - setTRAP (TRAP_PRV); - setCPUERR (CPUE_HALT); } - else setTRAP (TRAP_ILL); /* no, ill inst */ - break; - case 1: /* WAIT */ - if (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 (2); /* skip CPU, sys reg */ - PIRQ = 0; /* clear PIRQ, STKLIM, */ - STKLIM = 0; /* MMR0<15:12,0>, */ - for (i = 0; i < IPL_HLVL; i++) int_req[i] = 0; - MMR0 = MMR0 & ~(MMR0_MME | MMR0_FREEZE); - MMR3 = 0; /* MMR3 */ - trap_req = trap_req & ~TRAP_INT; - dsenable = calc_ds (cm); } - break; - -/* Opcode 0: specials, continued */ + 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) && + (!CPUT (CPUT_J) || ((MAINT & MAINT_HTRAP) == 0))) + reason = STOP_HALT; + else if (CPUT (HAS_HALT4)) { /* priv trap? */ + setTRAP (TRAP_PRV); + setCPUERR (CPUE_HALT); + } + else setTRAP (TRAP_ILL); /* no, ill inst */ + break; + case 1: /* WAIT */ + if (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 (2); /* skip CPU, sys reg */ + PIRQ = 0; /* clear PIRQ, STKLIM, */ + STKLIM = 0; /* MMR0<15:12,0>, */ + for (i = 0; i < IPL_HLVL; i++) int_req[i] = 0; + MMR0 = MMR0 & ~(MMR0_MME | MMR0_FREEZE); + MMR3 = 0; /* MMR3 */ + trap_req = trap_req & ~TRAP_INT; + dsenable = calc_ds (cm); + } + break; + case 6: /* RTT */ + if (!CPUT (HAS_RTT)) { + setTRAP (TRAP_ILL); + break; + } + case 2: /* RTI */ + src = ReadW (SP | dsenable); + src2 = ReadW (((SP + 2) & 0177777) | dsenable); + STACKFILE[cm] = SP = (SP + 4) & 0177777; + oldrs = rs; + put_PSW (src2, (cm != MD_KER)); /* store PSW, prot */ + 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); + trap_req = calc_ints (ipl, trap_req); + JMP_PC (src); + if (CPUT (HAS_RTT) && tbit && /* RTT impl? */ + (IR == 000002)) setTRAP (TRAP_TRC); /* RTI immed trap */ + break; + case 7: /* MFPT */ + if (CPUT (HAS_MFPT)) /* implemented? */ + R[0] = cpu_tab[cpu_model].mfpt; /* get type */ + else setTRAP (TRAP_ILL); + break; + } /* end switch no ops */ + break; /* end case no ops */ - case 6: /* RTT */ - if (!CPUT (HAS_RTT)) { - setTRAP (TRAP_ILL); - break; } - case 2: /* RTI */ - src = ReadW (SP | dsenable); - src2 = ReadW (((SP + 2) & 0177777) | dsenable); - STACKFILE[cm] = SP = (SP + 4) & 0177777; - oldrs = rs; - put_PSW (src2, (cm != MD_KER)); /* store PSW, prot */ - 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); - trap_req = calc_ints (ipl, trap_req); - JMP_PC (src); - if (CPUT (HAS_RTT) && tbit && /* RTT impl? */ - (IR == 000002)) setTRAP (TRAP_TRC); /* RTI immed trap */ - break; - case 7: /* MFPT */ - if (CPUT (HAS_MFPT)) /* implemented? */ - R[0] = cpu_tab[cpu_model].mfpt; /* get type */ - else setTRAP (TRAP_ILL); - break; } /* end switch no ops */ - break; /* end case no ops */ - -/* Opcode 0: specials, continued */ + case 001: /* JMP */ + if (dstreg) setTRAP (CPUT (HAS_JREG4)? TRAP_PRV: TRAP_ILL); + else { + dst = GeteaW (dstspec) & 0177777; /* get eff addr */ + if (CPUT (CPUT_05|CPUT_20) && /* 11/05, 11/20 */ + ((dstspec & 070) == 020)) /* JMP (R)+? */ + dst = R[dstspec & 07]; /* use post incr */ + JMP_PC (dst); + } + break; /* end JMP */ - case 001: /* JMP */ - if (dstreg) setTRAP (CPUT (HAS_JREG4)? TRAP_PRV: TRAP_ILL); - else { - dst = GeteaW (dstspec) & 0177777; /* get eff addr */ - if (CPUT (CPUT_05|CPUT_20) && /* 11/05, 11/20 */ - ((dstspec & 070) == 020)) /* JMP (R)+? */ - dst = R[dstspec & 07]; /* use post incr */ - JMP_PC (dst); } - 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 (CPUT (HAS_SPL)) { - if (cm == MD_KER) ipl = IR & 07; - trap_req = calc_ints (ipl, trap_req); } - else setTRAP (TRAP_ILL); - 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); - if (!CPUT (CPUT_20)) V = 0; - C = 0; - if (dstreg) R[dstspec] = dst; - else PWriteW (dst, last_pa); - break; /* end SWAB */ - -/* Opcode 0: branches, JSR */ + 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 (CPUT (HAS_SPL)) { + if (cm == MD_KER) ipl = IR & 07; + trap_req = calc_ints (ipl, trap_req); + } + else setTRAP (TRAP_ILL); + 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 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 (CPUT (HAS_JREG4)? TRAP_PRV: TRAP_ILL); - else { - srcspec = srcspec & 07; - dst = GeteaW (dstspec); - if (CPUT (CPUT_05|CPUT_20) && /* 11/05, 11/20 */ - ((dstspec & 070) == 020)) /* JSR (R)+? */ - dst = R[dstspec & 07]; /* use post incr */ - SP = (SP - 2) & 0177777; - if (update_MM) MMR1 = calc_MMR1 (0366); - WriteW (R[srcspec], SP | dsenable); - if ((cm == MD_KER) && (SP < (STKLIM + STKL_Y))) - set_stack_trap (SP); - R[srcspec] = PC; - JMP_PC (dst & 0177777); } - break; /* end JSR */ - -/* Opcode 0: SOPs */ + 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); + if (!CPUT (CPUT_20)) V = 0; + C = 0; + if (dstreg) R[dstspec] = dst; + else PWriteW (dst, last_pa); + break; /* end SWAB */ - 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 004: case 005: /* BR */ + BRANCH_F (IR); + break; - 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 + case 006: case 007: /* BR */ + BRANCH_B (IR); + break; - Notes: + 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 (CPUT (HAS_JREG4)? TRAP_PRV: TRAP_ILL); + else { + srcspec = srcspec & 07; + dst = GeteaW (dstspec); + if (CPUT (CPUT_05|CPUT_20) && /* 11/05, 11/20 */ + ((dstspec & 070) == 020)) /* JSR (R)+? */ + dst = R[dstspec & 07]; /* use post incr */ + SP = (SP - 2) & 0177777; + if (update_MM) MMR1 = calc_MMR1 (0366); + WriteW (R[srcspec], SP | dsenable); + if ((cm == MD_KER) && (SP < (STKLIM + STKL_Y))) + set_stack_trap (SP); + R[srcspec] = PC; + JMP_PC (dst & 0177777); + } + break; /* end JSR */ + + 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; + + 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; + +/* Notes: - MxPI must mask GeteaW returned address to force ispace - MxPI must set MMR1 for SP recovery in case of fault */ - case 064: /* MARK */ - if (CPUT (HAS_MARK)) { - i = (PC + dstspec + dstspec) & 0177777; - JMP_PC (R[5]); - R[5] = ReadW (i | dsenable); - SP = (i + 2) & 0177777; } - else setTRAP (TRAP_ILL); - break; - case 065: /* MFPI */ - if (CPUT (HAS_MXPY)) { - 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 + STKL_Y))) - set_stack_trap (SP); } - else setTRAP (TRAP_ILL); - break; - case 066: /* MTPI */ - if (CPUT (HAS_MXPY)) { - 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)); } - else setTRAP (TRAP_ILL); - break; - case 067: /* SXT */ - if (CPUT (HAS_SXS)) { - dst = N? 0177777: 0; - Z = N ^ 1; - V = 0; - if (dstreg) R[dstspec] = dst; - else WriteW (dst, GeteaW (dstspec)); } - else setTRAP (TRAP_ILL); - break; - -/* Opcode 0: SOPs, continued */ + case 064: /* MARK */ + if (CPUT (HAS_MARK)) { + i = (PC + dstspec + dstspec) & 0177777; + JMP_PC (R[5]); + R[5] = ReadW (i | dsenable); + SP = (i + 2) & 0177777; + } + else setTRAP (TRAP_ILL); + break; + + case 065: /* MFPI */ + if (CPUT (HAS_MXPY)) { + 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 + STKL_Y))) + set_stack_trap (SP); + } + else setTRAP (TRAP_ILL); + break; + + case 066: /* MTPI */ + if (CPUT (HAS_MXPY)) { + 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)); + } + else setTRAP (TRAP_ILL); + break; + + case 067: /* SXT */ + if (CPUT (HAS_SXS)) { + dst = N? 0177777: 0; + Z = N ^ 1; + V = 0; + if (dstreg) R[dstspec] = dst; + else WriteW (dst, GeteaW (dstspec)); + } + else setTRAP (TRAP_ILL); + break; + + case 070: /* CSM */ + if (CPUT (HAS_CSM) && (MMR3 & MMR3_CSM) || (cm != MD_KER)) { + dst = dstreg? R[dstspec]: ReadW (GeteaW (dstspec)); + PSW = get_PSW () & ~PSW_CC; /* PSW, cc = 0 */ + 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); + } + else setTRAP (TRAP_ILL); + break; + + case 072: /* TSTSET */ + if (CPUT (HAS_TSWLK) && !dstreg) { + 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 */ + } + else setTRAP (TRAP_ILL); + break; + + case 073: /* WRTLCK */ + if (CPUT (HAS_TSWLK) && !dstreg) { + N = GET_SIGN_W (R[0]); + Z = GET_Z (R[0]); + V = 0; + WriteW (R[0], GeteaW (dstspec)); + } + else setTRAP (TRAP_ILL); + break; + + default: + setTRAP (TRAP_ILL); + break; + } /* end switch SOPs */ + break; /* end case 000 */ - case 070: /* CSM */ - if (CPUT (HAS_CSM) && (MMR3 & MMR3_CSM) || (cm != MD_KER)) { - dst = dstreg? R[dstspec]: ReadW (GeteaW (dstspec)); - PSW = get_PSW () & ~PSW_CC; /* PSW, cc = 0 */ - 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); } - else setTRAP (TRAP_ILL); - break; - case 072: /* TSTSET */ - if (CPUT (HAS_TSWLK) && !dstreg) { - 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 */ - else setTRAP (TRAP_ILL); - break; - case 073: /* WRTLCK */ - if (CPUT (HAS_TSWLK) && !dstreg) { - N = GET_SIGN_W (R[0]); - Z = GET_Z (R[0]); - V = 0; - WriteW (R[0], GeteaW (dstspec)); } - else setTRAP (TRAP_ILL); - 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. @@ -1176,97 +1232,114 @@ case 000: Cmp: v = [sign (src) != sign (src2)] and [sign (src2) = sign (result)] */ -case 001: /* MOV */ - if (CPUT (IS_SDSD) && 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 (CPUT (IS_SDSD) && 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 (CPUT (IS_SDSD) && 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 (CPUT (IS_SDSD) && 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 (CPUT (IS_SDSD) && 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 (CPUT (IS_SDSD) && 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; - + case 001: /* MOV */ + if (CPUT (IS_SDSD) && 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 (CPUT (IS_SDSD) && 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 (CPUT (IS_SDSD) && 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 (CPUT (IS_SDSD) && 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 (CPUT (IS_SDSD) && 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 (CPUT (IS_SDSD) && 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. + 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). @@ -1275,486 +1348,559 @@ case 006: /* ADD */ 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 */ - if (!CPUO (OPT_EIS)) { - setTRAP (TRAP_ILL); - break; } - 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 */ - if (!CPUO (OPT_EIS)) { - setTRAP (TRAP_ILL); - break; } - 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 007: + srcspec = srcspec & 07; + switch ((IR >> 9) & 07) { /* decode IR<11:9> */ - case 2: /* ASH */ - if (!CPUO (OPT_EIS)) { - setTRAP (TRAP_ILL); - break; } - 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 */ - if (!CPUO (OPT_EIS)) { - setTRAP (TRAP_ILL); - break; } - 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 0: /* MUL */ + if (!CPUO (OPT_EIS)) { + setTRAP (TRAP_ILL); + break; + } + 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 */ + if (!CPUO (OPT_EIS)) { + setTRAP (TRAP_ILL); + break; + } + 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; + + case 2: /* ASH */ + if (!CPUO (OPT_EIS)) { + setTRAP (TRAP_ILL); + break; + } + 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 */ + if (!CPUO (OPT_EIS)) { + setTRAP (TRAP_ILL); + break; + } + 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; + + case 4: /* XOR */ + if (CPUT (HAS_SXS)) { + 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); + } + else setTRAP (TRAP_ILL); + break; + + case 5: /* FIS */ + if (CPUO (OPT_FIS)) fis11 (IR); + else setTRAP (TRAP_ILL); + break; + + case 6: /* CIS */ + if (CPUT (CPUT_60) && (cm == MD_KER) && /* 11/60 MED? */ + (IR == 076600)) { + ReadE (PC | isenable); /* read immediate */ + PC = (PC + 2) & 0177777; + } + else if (CPUO (OPT_CIS)) cis11 (IR); + else setTRAP (TRAP_ILL); + break; + + case 7: /* SOB */ + if (CPUT (HAS_SXS)) { + R[srcspec] = (R[srcspec] - 1) & 0177777; + if (R[srcspec]) { + JMP_PC ((PC - dstspec - dstspec) & 0177777); + } + } + else setTRAP (TRAP_ILL); + break; + } /* end switch EIS */ + break; /* end case 007 */ - case 4: /* XOR */ - if (CPUT (HAS_SXS)) { - 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); } - else setTRAP (TRAP_ILL); - break; - case 5: /* FIS */ - if (CPUO (OPT_FIS)) fis11 (IR); - else setTRAP (TRAP_ILL); - break; - case 6: /* CIS */ - if (CPUT (CPUT_60) && (cm == MD_KER) && /* 11/60 MED? */ - (IR == 076600)) { - ReadE (PC | isenable); /* read immediate */ - PC = (PC + 2) & 0177777; } - else if (CPUO (OPT_CIS)) cis11 (IR); - else setTRAP (TRAP_ILL); - break; - case 7: /* SOB */ - if (CPUT (HAS_SXS)) { - R[srcspec] = (R[srcspec] - 1) & 0177777; - if (R[srcspec]) { - JMP_PC ((PC - dstspec - dstspec) & 0177777); } } - else setTRAP (TRAP_ILL); - 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 010: + switch ((IR >> 6) & 077) { /* decode IR<11:6> */ - 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 000: case 001: /* BPL */ + if (N == 0) { BRANCH_F (IR); } + break; - 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 + case 002: case 003: /* BPL */ + if (N == 0) { BRANCH_B (IR); } + break; - Notes: + 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; + + 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; + + 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; +/* 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 */ - if (CPUT (HAS_MXPS)) { - 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; } - else setTRAP (TRAP_ILL); - break; - case 065: /* MFPD */ - if (CPUT (HAS_MXPY)) { - 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 + STKL_Y))) - set_stack_trap (SP); } - else setTRAP (TRAP_ILL); - break; - case 066: /* MTPD */ - if (CPUT (HAS_MXPY)) { - 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)); } - else setTRAP (TRAP_ILL); - break; - case 067: /* MFPS */ - if (CPUT (HAS_MXPS)) { - dst = get_PSW () & 0377; - 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)); } - else setTRAP (TRAP_ILL); - break; - default: - setTRAP (TRAP_ILL); - break; } /* end switch SOPs */ - break; /* end case 010 */ - + case 064: /* MTPS */ + if (CPUT (HAS_MXPS)) { + 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; + } + else setTRAP (TRAP_ILL); + break; + + case 065: /* MFPD */ + if (CPUT (HAS_MXPY)) { + 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 + STKL_Y))) + set_stack_trap (SP); + } + else setTRAP (TRAP_ILL); + break; + + case 066: /* MTPD */ + if (CPUT (HAS_MXPY)) { + 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)); + } + else setTRAP (TRAP_ILL); + break; + + case 067: /* MFPS */ + if (CPUT (HAS_MXPS)) { + dst = get_PSW () & 0377; + 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)); + } + else setTRAP (TRAP_ILL); + 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 (CPUT (IS_SDSD) && 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 (CPUT (IS_SDSD) && 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 (CPUT (IS_SDSD) && 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 (CPUT (IS_SDSD) && 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 (CPUT (IS_SDSD) && 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 (CPUT (IS_SDSD) && 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; - + case 011: /* MOVB */ + if (CPUT (IS_SDSD) && 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 (CPUT (IS_SDSD) && 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 (CPUT (IS_SDSD) && 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 (CPUT (IS_SDSD) && 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 (CPUT (IS_SDSD) && 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 (CPUT (IS_SDSD) && 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: - if (CPUO (OPT_FPP)) fp11 (IR); /* call fpp */ - else setTRAP (TRAP_ILL); - break; /* end case 017 */ - } /* end switch op */ -} /* end main loop */ + case 017: + if (CPUO (OPT_FPP)) fp11 (IR); /* call fpp */ + else setTRAP (TRAP_ILL); + break; /* end case 017 */ + } /* end switch op */ + } /* end main loop */ /* Simulation halted */ @@ -1762,20 +1908,20 @@ PSW = get_PSW (); 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 */ +pcq_r->qptr = pcq_p; /* update pc q ptr */ set_r_display (rs, cm); return reason; } - + /* Effective address calculations Inputs: - spec = specifier <5:0> + spec = specifier <5:0> Outputs: - ea = effective address - <15:0> = virtual address - <16> = instruction/data data space - <18:17> = mode + 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 @@ -1783,19 +1929,19 @@ return reason; 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 + 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 @@ -1808,129 +1954,146 @@ return reason; - 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 + 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 ((reg == 6) && (cm == MD_KER) && (adr < (STKLIM + STKL_Y))) - set_stack_trap (adr); - return (adr | ds); -case 5: /* @-(R) */ - adr = R[reg] = (R[reg] - 2) & 0177777; - if (update_MM) MMR1 = calc_MMR1 (0360 | reg); - if ((reg == 6) && (cm == MD_KER) && (adr < (STKLIM + STKL_Y))) - set_stack_trap (adr); - 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 */ +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 ((reg == 6) && (cm == MD_KER) && (adr < (STKLIM + STKL_Y))) + set_stack_trap (adr); + return (adr | ds); + + case 5: /* @-(R) */ + adr = R[reg] = (R[reg] - 2) & 0177777; + if (update_MM) MMR1 = calc_MMR1 (0360 | reg); + if ((reg == 6) && (cm == MD_KER) && (adr < (STKLIM + STKL_Y))) + set_stack_trap (adr); + 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 ((reg == 6) && (cm == MD_KER) && (adr < (STKLIM + STKL_Y))) - set_stack_trap (adr); - return (adr | ds); -case 5: /* @-(R) */ - adr = R[reg] = (R[reg] - 2) & 0177777; - if (update_MM) MMR1 = calc_MMR1 (0360 | reg); - if ((reg == 6) && (cm == MD_KER) && (adr < (STKLIM + STKL_Y))) - set_stack_trap (adr); - 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 */ +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 ((reg == 6) && (cm == MD_KER) && (adr < (STKLIM + STKL_Y))) + set_stack_trap (adr); + return (adr | ds); + + case 5: /* @-(R) */ + adr = R[reg] = (R[reg] - 2) & 0177777; + if (update_MM) MMR1 = calc_MMR1 (0360 | reg); + if ((reg == 6) && (cm == MD_KER) && (adr < (STKLIM + STKL_Y))) + set_stack_trap (adr); + 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 + va = virtual address, <18:16> = mode, I/D space Outputs: - data = data read from memory or I/O space + data = data read from memory or I/O space */ int32 ReadE (int32 va) { int32 pa, data; -if ((va & 1) && CPUT (HAS_ODD)) { /* 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 */ - (CPUT (CPUT_J) && (pa >= IOBA_CPU))) { /* or J11 int reg? */ - setCPUERR (CPUE_NXM); - ABORT (TRAP_NXM); } -if (iopageR (&data, pa, READ) != SCPE_OK) { /* invalid I/O addr? */ - setCPUERR (CPUE_TMO); - ABORT (TRAP_NXM); } +if ((va & 1) && CPUT (HAS_ODD)) { /* 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 */ + (CPUT (CPUT_J) && (pa >= IOBA_CPU))) { /* or J11 int reg? */ + 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; } @@ -1938,17 +2101,20 @@ int32 ReadW (int32 va) { int32 pa, data; -if ((va & 1) && CPUT (HAS_ODD)) { /* 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); } +if ((va & 1) && CPUT (HAS_ODD)) { /* 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; } @@ -1956,32 +2122,37 @@ int32 ReadB (int32 va) { int32 pa, data; -pa = relocR (va); /* relocate */ +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); } +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) && CPUT (HAS_ODD)) { /* 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); } +if ((va & 1) && CPUT (HAS_ODD)) { /* 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; } @@ -1989,24 +2160,26 @@ int32 ReadMB (int32 va) { int32 data; -last_pa = relocW (va); /* reloc, wrt chk */ +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? 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 + data = data to be written + va = virtual address, <18:16> = mode, I/D space, or + pa = physical address Outputs: none */ @@ -2014,19 +2187,23 @@ void WriteW (int32 data, int32 va) { int32 pa; -if ((va & 1) && CPUT (HAS_ODD)) { /* 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); } +if ((va & 1) && CPUT (HAS_ODD)) { /* 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; } @@ -2034,55 +2211,64 @@ 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); } +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); } +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); } +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 + va = virtual address, <18:16> = mode, I/D space Outputs: - pa = physical address + pa = physical address On aborts, this routine aborts back to the top level simulator with an appropriate trap code. @@ -2097,88 +2283,96 @@ int32 relocR (int32 va) { int32 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> */ - if ((apr & PDR_PRD) != 2) /* not 2, 6? */ - relocR_test (va, apridx); /* long test */ - if (PLF_test (va, apr)) /* pg lnt error? */ - reloc_abort (MMR0_PL, apridx); - 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; } +if (MMR0 & MMR0_MME) { /* if mmgt */ + apridx = (va >> VA_V_APF) & 077; /* index into APR */ + apr = APRFILE[apridx]; /* with va<18:13> */ + if ((apr & PDR_PRD) != 2) /* not 2, 6? */ + relocR_test (va, apridx); /* long test */ + if (PLF_test (va, apr)) /* pg lnt error? */ + reloc_abort (MMR0_PL, apridx); + 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; } /* Read relocation, access control field != read only or read/write - ACF value 11/45,11/70 all others + ACF value 11/45,11/70 all others - 0 abort NR abort NR - 1 trap - - 2 ok ok - 3 abort NR - - 4 trap abort NR - 5 ok - - 6 ok ok - 7 abort NR - + 0 abort NR abort NR + 1 trap - + 2 ok ok + 3 abort NR - + 4 trap abort NR + 5 ok - + 6 ok ok + 7 abort NR - */ void relocR_test (int32 va, int32 apridx) { int32 apr, err; -err = 0; /* init status */ -apr = APRFILE[apridx]; /* get APR */ -switch (apr & PDR_ACF) { /* case on ACF */ -case 1: case 4: /* trap read */ - if (CPUT (HAS_MMTR)) { /* traps implemented? */ - APRFILE[apridx] = APRFILE[apridx] | PDR_A; /* set A */ - if (MMR0 & MMR0_TENB) { /* traps enabled? */ - if (update_MM) MMR0 = /* update MMR0 */ - (MMR0 & ~MMR0_PAGE) | (apridx << MMR0_V_PAGE); - MMR0 = MMR0 | MMR0_TRAP; /* set trap flag */ - setTRAP (TRAP_MME); } /* set trap */ - return; } /* continue op */ - /* not impl, abort NR */ -case 0: case 3: case 7: /* non-resident */ - err = MMR0_NR; /* set MMR0 */ - break; /* go test PLF, abort */ -case 2: case 5: case 6: /* readable */ - return; /* continue */ - } /* end switch */ -if (PLF_test (va, apr)) err = err | MMR0_PL; /* pg lnt error? */ +err = 0; /* init status */ +apr = APRFILE[apridx]; /* get APR */ +switch (apr & PDR_ACF) { /* case on ACF */ + + case 1: case 4: /* trap read */ + if (CPUT (HAS_MMTR)) { /* traps implemented? */ + APRFILE[apridx] = APRFILE[apridx] | PDR_A; /* set A */ + if (MMR0 & MMR0_TENB) { /* traps enabled? */ + if (update_MM) MMR0 = /* update MMR0 */ + (MMR0 & ~MMR0_PAGE) | (apridx << MMR0_V_PAGE); + MMR0 = MMR0 | MMR0_TRAP; /* set trap flag */ + setTRAP (TRAP_MME); /* set trap */ + } + return; /* continue op */ + } /* not impl, abort NR */ + case 0: case 3: case 7: /* non-resident */ + err = MMR0_NR; /* set MMR0 */ + break; /* go test PLF, abort */ + + case 2: case 5: case 6: /* readable */ + return; /* continue */ + } /* end switch */ + +if (PLF_test (va, apr)) err = err | MMR0_PL; /* pg lnt error? */ reloc_abort (err, apridx); return; } t_bool PLF_test (int32 va, int32 apr) { -int32 dbn = va & VA_BN; /* extr block num */ -int32 plf = (apr & PDR_PLF) >> 2; /* extr page length */ +int32 dbn = va & VA_BN; /* extr block num */ +int32 plf = (apr & PDR_PLF) >> 2; /* extr page length */ -return ((apr & PDR_ED)? (dbn < plf): (dbn > plf)); /* pg lnt error? */ +return ((apr & PDR_ED)? (dbn < plf): (dbn > plf)); /* pg lnt error? */ } void reloc_abort (int32 err, int32 apridx) { -if (update_MM) MMR0 = /* update MMR0 */ - (MMR0 & ~MMR0_PAGE) | (apridx << MMR0_V_PAGE); -APRFILE[apridx] = APRFILE[apridx] | PDR_A; /* set A */ -MMR0 = MMR0 | err; /* set aborts */ -ABORT (TRAP_MME); /* abort ref */ +if (update_MM) MMR0 = /* update MMR0 */ + (MMR0 & ~MMR0_PAGE) | (apridx << MMR0_V_PAGE); +APRFILE[apridx] = APRFILE[apridx] | PDR_A; /* set A */ +MMR0 = MMR0 | err; /* set aborts */ +ABORT (TRAP_MME); /* abort ref */ return; } - + /* Relocate virtual address, write access Inputs: - va = virtual address, <18:16> = mode, I/D space + va = virtual address, <18:16> = mode, I/D space Outputs: - pa = physical address + pa = physical address On aborts, this routine aborts back to the top level simulator with an appropriate trap code. @@ -2193,75 +2387,83 @@ int32 relocW (int32 va) { int32 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> */ - if ((apr & PDR_ACF) != 6) /* not writeable? */ - relocW_test (va, apridx); /* long test */ - if (PLF_test (va, apr)) /* pg lnt error? */ - reloc_abort (MMR0_PL, apridx); - 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; } +if (MMR0 & MMR0_MME) { /* if mmgt */ + apridx = (va >> VA_V_APF) & 077; /* index into APR */ + apr = APRFILE[apridx]; /* with va<18:13> */ + if ((apr & PDR_ACF) != 6) /* not writeable? */ + relocW_test (va, apridx); /* long test */ + if (PLF_test (va, apr)) /* pg lnt error? */ + reloc_abort (MMR0_PL, apridx); + 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; } /* Write relocation, access control field != read/write - ACF value 11/45,11/70 all others + ACF value 11/45,11/70 all others - 0 abort NR abort NR - 1 abort RO - - 2 abort RO abort RO - 3 abort NR - - 4 trap abort NR - 5 trap - - 6 ok ok - 7 abort NR - + 0 abort NR abort NR + 1 abort RO - + 2 abort RO abort RO + 3 abort NR - + 4 trap abort NR + 5 trap - + 6 ok ok + 7 abort NR - */ void relocW_test (int32 va, int32 apridx) { int32 apr, err; -err = 0; /* init status */ -apr = APRFILE[apridx]; /* get APR */ -switch (apr & PDR_ACF) { /* case on ACF */ -case 4: case 5: /* trap write */ - if (CPUT (HAS_MMTR)) { /* traps implemented? */ - APRFILE[apridx] = APRFILE[apridx] | PDR_A; /* set A */ - if (MMR0 & MMR0_TENB) { /* traps enabled? */ - if (update_MM) MMR0 = /* update MMR0 */ - (MMR0 & ~MMR0_PAGE) | (apridx << MMR0_V_PAGE); - MMR0 = MMR0 | MMR0_TRAP; /* set trap flag */ - setTRAP (TRAP_MME); } /* set trap */ - return; } /* continue op */ - /* not impl, abort NR */ -case 0: case 3: case 7: /* non-resident */ - err = MMR0_NR; /* MMR0 status */ - break; /* go test PLF, abort */ -case 1: case 2: /* read only */ - err = MMR0_RO; /* MMR0 status */ - break; -case 6: /* read/write */ - return; /* continue */ - } /* end switch */ -if (PLF_test (va, apr)) err = err | MMR0_PL; /* pg lnt error? */ +err = 0; /* init status */ +apr = APRFILE[apridx]; /* get APR */ +switch (apr & PDR_ACF) { /* case on ACF */ + + case 4: case 5: /* trap write */ + if (CPUT (HAS_MMTR)) { /* traps implemented? */ + APRFILE[apridx] = APRFILE[apridx] | PDR_A; /* set A */ + if (MMR0 & MMR0_TENB) { /* traps enabled? */ + if (update_MM) MMR0 = /* update MMR0 */ + (MMR0 & ~MMR0_PAGE) | (apridx << MMR0_V_PAGE); + MMR0 = MMR0 | MMR0_TRAP; /* set trap flag */ + setTRAP (TRAP_MME); /* set trap */ + } + return; /* continue op */ + } /* not impl, abort NR */ + case 0: case 3: case 7: /* non-resident */ + err = MMR0_NR; /* MMR0 status */ + break; /* go test PLF, abort */ + + case 1: case 2: /* read only */ + err = MMR0_RO; /* MMR0 status */ + break; + + case 6: /* read/write */ + return; /* continue */ + } /* end switch */ +if (PLF_test (va, apr)) err = err | MMR0_PL; /* pg lnt error? */ reloc_abort (err, apridx); return; } - + /* Relocate virtual address, console access Inputs: - va = virtual address - sw = switches + va = virtual address + sw = switches Outputs: - pa = physical address + pa = physical address On aborts, this routine returns MAXMEMSIZE */ @@ -2269,75 +2471,89 @@ 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; } +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; } - + /* Memory management registers - 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 + 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 MMR012_rd (int32 *data, int32 pa, int32 access) { -switch ((pa >> 1) & 3) { /* decode pa<2:1> */ -case 0: /* SR */ - return SCPE_NXM; -case 1: /* MMR0 */ - *data = MMR0 & cpu_tab[cpu_model].mm0; - break; -case 2: /* MMR1 */ - *data = MMR1; - break; -case 3: /* MMR2 */ - *data = MMR2; - break; } /* end switch pa */ +switch ((pa >> 1) & 3) { /* decode pa<2:1> */ + + case 0: /* SR */ + return SCPE_NXM; + + case 1: /* MMR0 */ + *data = MMR0 & cpu_tab[cpu_model].mm0; + break; + + case 2: /* MMR1 */ + *data = MMR1; + break; + + case 3: /* MMR2 */ + *data = MMR2; + break; + } + /* end switch pa */ return SCPE_OK; } t_stat MMR012_wr (int32 data, int32 pa, int32 access) { -switch ((pa >> 1) & 3) { /* decode pa<2:1> */ -case 0: /* DR */ - return SCPE_NXM; -case 1: /* MMR0 */ - if (access == WRITEB) data = (pa & 1)? - (MMR0 & 0377) | (data << 8): (MMR0 & ~0377) | data; - data = data & cpu_tab[cpu_model].mm0; - MMR0 = (MMR0 & ~MMR0_WR) | (data & MMR0_WR); - return SCPE_OK; -default: /* MMR1, MMR2 */ - return SCPE_OK; } /* end switch pa */ +switch ((pa >> 1) & 3) { /* decode pa<2:1> */ + + case 0: /* DR */ + return SCPE_NXM; + + case 1: /* MMR0 */ + if (access == WRITEB) data = (pa & 1)? + (MMR0 & 0377) | (data << 8): (MMR0 & ~0377) | data; + data = data & cpu_tab[cpu_model].mm0; + MMR0 = (MMR0 & ~MMR0_WR) | (data & MMR0_WR); + return SCPE_OK; + + default: /* MMR1, MMR2 */ + return SCPE_OK; + } /* end switch pa */ } -t_stat MMR3_rd (int32 *data, int32 pa, int32 access) /* MMR3 */ +t_stat MMR3_rd (int32 *data, int32 pa, int32 access) /* MMR3 */ { *data = MMR3 & cpu_tab[cpu_model].mm3; return SCPE_OK; } -t_stat MMR3_wr (int32 data, int32 pa, int32 access) /* MMR3 */ +t_stat MMR3_wr (int32 data, int32 pa, int32 access) /* MMR3 */ { if (pa & 1) return SCPE_OK; MMR3 = data & cpu_tab[cpu_model].mm3; @@ -2345,21 +2561,21 @@ cpu_bme = (MMR3 & MMR3_BME) && (cpu_opt & OPT_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 + 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> + 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: the A,W bits are read only; they are cleared by any write to an APR */ @@ -2368,10 +2584,10 @@ 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 */ +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 */ if (left) *data = (APRFILE[idx] >> 16) & cpu_tab[cpu_model].par; else *data = APRFILE[idx] & cpu_tab[cpu_model].pdr; return SCPE_OK; @@ -2381,21 +2597,21 @@ 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 */ +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 */ if (left) curr = (APRFILE[idx] >> 16) & cpu_tab[cpu_model].par; else curr = APRFILE[idx] & cpu_tab[cpu_model].pdr; if (access == WRITEB) data = (pa & 1)? - (curr & 0377) | (data << 8): (curr & ~0377) | data; + (curr & 0377) | (data << 8): (curr & ~0377) | data; if (left) APRFILE[idx] = ((APRFILE[idx] & 0177777) | - (((uint32) (data & cpu_tab[cpu_model].par)) << 16)) & ~(PDR_A|PDR_W); + (((uint32) (data & cpu_tab[cpu_model].par)) << 16)) & ~(PDR_A|PDR_W); else APRFILE[idx] = ((APRFILE[idx] & ~0177777) | - (data & cpu_tab[cpu_model].pdr)) & ~(PDR_A|PDR_W); + (data & cpu_tab[cpu_model].pdr)) & ~(PDR_A|PDR_W); return SCPE_OK; } - + /* Explicit PSW read */ t_stat PSW_rd (int32 *data, int32 pa, int32 access) @@ -2410,10 +2626,10 @@ return SCPE_OK; int32 get_PSW (void) { return (cm << PSW_V_CM) | (pm << PSW_V_PM) | - (rs << PSW_V_RS) | (fpd << PSW_V_FPD) | - (ipl << PSW_V_IPL) | (tbit << PSW_V_TBIT) | - (N << PSW_V_N) | (Z << PSW_V_Z) | - (V << PSW_V_V) | (C << PSW_V_C); + (rs << PSW_V_RS) | (fpd << PSW_V_FPD) | + (ipl << PSW_V_IPL) | (tbit << PSW_V_TBIT) | + (N << PSW_V_N) | (Z << PSW_V_Z) | + (V << PSW_V_V) | (C << PSW_V_C); } /* Explicit PSW write - T-bit may be protected */ @@ -2422,22 +2638,25 @@ t_stat PSW_wr (int32 data, int32 pa, int32 access) { int32 i, curr, oldrs; -if (access == WRITEC) { /* console access? */ - PSW = data & cpu_tab[cpu_model].psw; - return SCPE_OK; } -curr = get_PSW (); /* get current */ -oldrs = rs; /* save reg set */ -STACKFILE[cm] = SP; /* save curr SP */ +if (access == WRITEC) { /* console access? */ + PSW = data & cpu_tab[cpu_model].psw; + return SCPE_OK; + } +curr = get_PSW (); /* get current */ +oldrs = rs; /* save reg set */ +STACKFILE[cm] = SP; /* save curr SP */ if (access == WRITEB) data = (pa & 1)? - (curr & 0377) | (data << 8): (curr & ~0377) | data; -if (!CPUT (HAS_EXPT)) /* expl T writes? */ - data = (data & ~PSW_TBIT) | (curr & PSW_TBIT); /* no, use old T */ -put_PSW (data, 0); /* call calc_is,ds */ -if (rs != oldrs) { /* switch reg set */ - for (i = 0; i < 6; i++) { - REGFILE[i][oldrs] = R[i]; - R[i] = REGFILE[i][rs]; } } -SP = STACKFILE[cm]; /* switch SP */ + (curr & 0377) | (data << 8): (curr & ~0377) | data; +if (!CPUT (HAS_EXPT)) /* expl T writes? */ + data = (data & ~PSW_TBIT) | (curr & PSW_TBIT); /* no, use old T */ +put_PSW (data, 0); /* call calc_is,ds */ +if (rs != oldrs) { /* switch reg set */ + for (i = 0; i < 6; i++) { + REGFILE[i][oldrs] = R[i]; + R[i] = REGFILE[i][rs]; + } + } +SP = STACKFILE[cm]; /* switch SP */ isenable = calc_is (cm); dsenable = calc_ds (cm); return SCPE_OK; @@ -2447,16 +2666,19 @@ return SCPE_OK; void put_PSW (int32 val, t_bool prot) { -val = val & cpu_tab[cpu_model].psw; /* mask off invalid bits */ -if (prot) { /* protected? */ - cm = cm | ((val >> PSW_V_CM) & 03); /* or to cm,pm,rs */ - pm = pm | ((val >> PSW_V_PM) & 03); /* can't change ipl */ - rs = rs | ((val >> PSW_V_RS) & 01); } -else { cm = (val >> PSW_V_CM) & 03; /* write cm,pm,rs,ipl */ - pm = (val >> PSW_V_PM) & 03; - rs = (val >> PSW_V_RS) & 01; - ipl = (val >> PSW_V_IPL) & 07; } -fpd = (val >> PSW_V_FPD) & 01; /* always writeable */ +val = val & cpu_tab[cpu_model].psw; /* mask off invalid bits */ +if (prot) { /* protected? */ + cm = cm | ((val >> PSW_V_CM) & 03); /* or to cm,pm,rs */ + pm = pm | ((val >> PSW_V_PM) & 03); /* can't change ipl */ + rs = rs | ((val >> PSW_V_RS) & 01); + } +else { + cm = (val >> PSW_V_CM) & 03; /* write cm,pm,rs,ipl */ + pm = (val >> PSW_V_PM) & 03; + rs = (val >> PSW_V_RS) & 01; + ipl = (val >> PSW_V_IPL) & 07; + } +fpd = (val >> PSW_V_FPD) & 01; /* always writeable */ tbit = (val >> PSW_V_TBIT) & 01; N = (val >> PSW_V_N) & 01; Z = (val >> PSW_V_Z) & 01; @@ -2473,19 +2695,40 @@ int32 pl; PIRQ = val & PIRQ_RW; pl = 0; -if (PIRQ & PIRQ_PIR1) { SET_INT (PIR1); pl = 0042; } +if (PIRQ & PIRQ_PIR1) { + SET_INT (PIR1); + pl = 0042; + } else CLR_INT (PIR1); -if (PIRQ & PIRQ_PIR2) { SET_INT (PIR2); pl = 0104; } +if (PIRQ & PIRQ_PIR2) { + SET_INT (PIR2); + pl = 0104; + } else CLR_INT (PIR2); -if (PIRQ & PIRQ_PIR3) { SET_INT (PIR3); pl = 0146; } +if (PIRQ & PIRQ_PIR3) { + SET_INT (PIR3); + pl = 0146; + } else CLR_INT (PIR3); -if (PIRQ & PIRQ_PIR4) { SET_INT (PIR4); pl = 0210; } +if (PIRQ & PIRQ_PIR4) { + SET_INT (PIR4); + pl = 0210; + } else CLR_INT (PIR4); -if (PIRQ & PIRQ_PIR5) { SET_INT (PIR5); pl = 0252; } +if (PIRQ & PIRQ_PIR5) { + SET_INT (PIR5); + pl = 0252; + } else CLR_INT (PIR5); -if (PIRQ & PIRQ_PIR6) { SET_INT (PIR6); pl = 0314; } +if (PIRQ & PIRQ_PIR6) { + SET_INT (PIR6); + pl = 0314; + } else CLR_INT (PIR6); -if (PIRQ & PIRQ_PIR7) { SET_INT (PIR7); pl = 0356; } +if (PIRQ & PIRQ_PIR7) { + SET_INT (PIR7); + pl = 0356; + } else CLR_INT (PIR7); PIRQ = PIRQ | pl; return; @@ -2495,22 +2738,25 @@ return; void set_stack_trap (int32 adr) { -if (CPUT (HAS_STKLF)) { /* fixed stack? */ - setTRAP (TRAP_YEL); /* always yellow trap */ - setCPUERR (CPUE_YEL); } -else if (CPUT (HAS_STKLR)) { /* register limit? */ - if (adr >= (STKLIM + STKL_R)) { /* yellow zone? */ - setTRAP (TRAP_YEL); /* still yellow trap */ - setCPUERR (CPUE_YEL); } - else { /* red zone abort */ - setCPUERR (CPUE_RED); - STACKFILE[MD_KER] = 4; - SP = 4; - ABORT (TRAP_RED); } - } -return; /* no stack limit */ +if (CPUT (HAS_STKLF)) { /* fixed stack? */ + setTRAP (TRAP_YEL); /* always yellow trap */ + setCPUERR (CPUE_YEL); + } +else if (CPUT (HAS_STKLR)) { /* register limit? */ + if (adr >= (STKLIM + STKL_R)) { /* yellow zone? */ + setTRAP (TRAP_YEL); /* still yellow trap */ + setCPUERR (CPUE_YEL); + } + else { /* red zone abort */ + setCPUERR (CPUE_RED); + STACKFILE[MD_KER] = 4; + SP = 4; + ABORT (TRAP_RED); + } + } +return; /* no stack limit */ } - + /* Reset routine */ t_stat cpu_reset (DEVICE *dptr) @@ -2524,7 +2770,7 @@ MMR2 = 0; MMR3 = 0; trap_req = 0; wait_state = 0; -if (M == NULL) M = calloc (MEMSIZE >> 1, sizeof (uint16)); +if (M == NULL) M = (uint16 *) calloc (MEMSIZE >> 1, sizeof (uint16)); if (M == NULL) return SCPE_MEM; pcq_r = find_reg ("PCQ", NULL, dptr); if (pcq_r) pcq_r->qptr = 0; @@ -2542,13 +2788,15 @@ 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 (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; } + *vptr = M[addr >> 1] & 0177777; + return SCPE_OK; + } if (addr < IOPAGEBASE) return SCPE_NXM; stat = iopageR (&iodata, addr, READC); *vptr = iodata; @@ -2559,13 +2807,15 @@ return stat; 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 (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; } + M[addr >> 1] = val & 0177777; + return SCPE_OK; + } if (addr < IOPAGEBASE) return SCPE_NXM; return iopageW ((int32) val, addr, WRITEC); } diff --git a/PDP11/pdp11_cpumod.c b/PDP11/pdp11_cpumod.c index f7923f1e..1463e717 100644 --- a/PDP11/pdp11_cpumod.c +++ b/PDP11/pdp11_cpumod.c @@ -19,14 +19,16 @@ 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 + 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. - system PDP-11 model-specific registers + system PDP-11 model-specific registers - 15-Feb-05 RMS Fixed bug in SHOW MODEL (from Sergey Okhapkin) - 19-Jan-05 RMS Added variable SYSID, MBRK write (from Tim Chapman) + 30-Aug-05 RMS Added additional 11/60 registers + 16-Aug-05 RMS Fixed C++ declaration and cast problems + 15-Feb-05 RMS Fixed bug in SHOW MODEL (from Sergey Okhapkin) + 19-Jan-05 RMS Added variable SYSID, MBRK write (from Tim Chapman) This module includes CPU- and system-specific registers, such as the Unibus map and control registers on 22b Unibus systems, the board registers for the @@ -43,31 +45,32 @@ /* Byte write macros for system registers */ #define ODD_IGN(cur) \ - if ((access == WRITEB) && (pa & 1)) return SCPE_OK + if ((access == WRITEB) && (pa & 1)) return SCPE_OK #define ODD_WO(cur) \ - if ((access == WRITEB) && (pa & 1)) cur = cur << 8 + if ((access == WRITEB) && (pa & 1)) cur = cur << 8 #define ODD_MRG(prv,cur) \ - if (access == WRITEB) cur = \ - ((pa & 1)? (((prv) & 0377) | ((cur) & 0177400)) : \ - (((prv) & 0177400) | ((cur) & 0377))) + if (access == WRITEB) cur = \ + ((pa & 1)? (((prv) & 0377) | ((cur) & 0177400)) : \ + (((prv) & 0177400) | ((cur) & 0377))) -int32 SR = 0; /* switch register */ -int32 DR = 0; /* display register */ -int32 MBRK = 0; /* 11/70 microbreak */ -int32 SYSID = 0x1234; /* 11/70 system ID */ -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 = 0; /* maint reg */ -int32 JCSR = 0; /* J11 control */ -int32 JPCR = 0; /* J11 page ctrl */ -int32 JASR = 0; /* J11 addtl status */ -int32 UDCR = 0; /* UBA diag ctrl */ -int32 UDDR = 0; /* UBA diag data */ -int32 UCSR = 0; /* UBA control */ -int32 uba_last = 0; /* UBA last mapped */ -int32 ub_map[UBM_LNT_LW] = { 0 }; /* UBA map array */ +int32 SR = 0; /* switch register */ +int32 DR = 0; /* display register */ +int32 MBRK = 0; /* 11/70 microbreak */ +int32 SYSID = 0x1234; /* 11/70 system ID */ +int32 WCS = 0; /* 11/60 WCS control */ +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 = 0; /* maint reg */ +int32 JCSR = 0; /* J11 control */ +int32 JPCR = 0; /* J11 page ctrl */ +int32 JASR = 0; /* J11 addtl status */ +int32 UDCR = 0; /* UBA diag ctrl */ +int32 UDDR = 0; /* UBA diag data */ +int32 UCSR = 0; /* UBA control */ +int32 uba_last = 0; /* UBA last mapped */ +int32 ub_map[UBM_LNT_LW] = { 0 }; /* UBA map array */ int32 toy_state = 0; uint8 toy_data[TOY_LNT] = { 0 }; static int32 clk_tps_map[4] = { 60, 60, 50, 800 }; @@ -158,122 +161,128 @@ DIB mmr3_dib = { IOBA_MMR3, IOLN_MMR3, &MMR3_rd, &MMR3_wr, 0 }; DIB ubm_dib = { IOBA_UBM, IOLN_UBM, &ubm_rd, &ubm_wr, 0 }; CPUTAB cpu_tab[MOD_MAX] = { - { "11/03", SOP_1103, OPT_1103, MEMSIZE64K, PSW_1103, - 0, 0, 0, 0, 0 }, - { "11/04", SOP_1104, OPT_1104, MEMSIZE64K, PSW_1104, - 0, 0, 0, 0, 0 }, - { "11/05", SOP_1105, OPT_1105, MEMSIZE64K, PSW_1105, - 0, 0, 0, 0, 0 }, - { "11/20", SOP_1120, OPT_1120, MEMSIZE64K, PSW_1120, - 0, 0, 0, 0, 0 }, - { "11/23", SOP_1123, OPT_1123, MAXMEMSIZE, PSW_F, - MFPT_F, PAR_F, PDR_F, MM0_F, MM3_F }, - { "11/23+", SOP_1123P, OPT_1123P, MAXMEMSIZE, PSW_F, - MFPT_F, PAR_F, PDR_F, MM0_F, MM3_F }, - { "11/24", SOP_1124, OPT_1124, MAXMEMSIZE, PSW_F, - MFPT_F, PAR_F, PDR_F, MM0_F, MM3_F }, - { "11/34", SOP_1134, OPT_1134, UNIMEMSIZE, PSW_1134, - 0, PAR_1134, PDR_1134, MM0_1134, 0 }, - { "11/40", SOP_1140, OPT_1140, UNIMEMSIZE, PSW_1140, - 0, PAR_1140, PDR_1140, MM0_1140, 0 }, - { "11/44", SOP_1144, OPT_1144, MAXMEMSIZE, PSW_1144, - MFPT_44, PAR_1144, PDR_1144, MM0_1144, MM3_1144 }, - { "11/45", SOP_1145, OPT_1145, UNIMEMSIZE, PSW_1145, - 0, PAR_1145, PDR_1145, MM0_1145, MM3_1145 }, - { "11/60", SOP_1160, OPT_1160, UNIMEMSIZE, PSW_1160, - 0, PAR_1160, PDR_1160, MM0_1160, 0 }, - { "11/70", SOP_1170, OPT_1170, MAXMEMSIZE, PSW_1170, - 0, PAR_1170, PDR_1170, MM0_1170, MM3_1170 }, - { "11/73", SOP_1173, OPT_1173, MAXMEMSIZE, PSW_J, - MFPT_J, PAR_J, PDR_J, MM0_J, MM3_J }, - { "11/53", SOP_1153, OPT_1153, MAXMEMSIZE, PSW_J, - MFPT_J, PAR_J, PDR_J, MM0_J, MM3_J }, - { "11/73B", SOP_1173B, OPT_1173B, MAXMEMSIZE, PSW_J, - MFPT_J, PAR_J, PDR_J, MM0_J, MM3_J }, - { "11/83", SOP_1183, OPT_1183, MAXMEMSIZE, PSW_J, - MFPT_J, PAR_J, PDR_J, MM0_J, MM3_J }, - { "11/84", SOP_1184, OPT_1184, MAXMEMSIZE, PSW_J, - MFPT_J, PAR_J, PDR_J, MM0_J, MM3_J }, - { "11/93", SOP_1193, OPT_1193, MAXMEMSIZE, PSW_J, - MFPT_J, PAR_J, PDR_J, MM0_J, MM3_J }, - { "11/94", SOP_1194, OPT_1194, MAXMEMSIZE, PSW_J, - MFPT_J, PAR_J, PDR_J, MM0_J, MM3_J } }; + { "11/03", SOP_1103, OPT_1103, MEMSIZE64K, PSW_1103, + 0, 0, 0, 0, 0 }, + { "11/04", SOP_1104, OPT_1104, MEMSIZE64K, PSW_1104, + 0, 0, 0, 0, 0 }, + { "11/05", SOP_1105, OPT_1105, MEMSIZE64K, PSW_1105, + 0, 0, 0, 0, 0 }, + { "11/20", SOP_1120, OPT_1120, MEMSIZE64K, PSW_1120, + 0, 0, 0, 0, 0 }, + { "11/23", SOP_1123, OPT_1123, MAXMEMSIZE, PSW_F, + MFPT_F, PAR_F, PDR_F, MM0_F, MM3_F }, + { "11/23+", SOP_1123P, OPT_1123P, MAXMEMSIZE, PSW_F, + MFPT_F, PAR_F, PDR_F, MM0_F, MM3_F }, + { "11/24", SOP_1124, OPT_1124, MAXMEMSIZE, PSW_F, + MFPT_F, PAR_F, PDR_F, MM0_F, MM3_F }, + { "11/34", SOP_1134, OPT_1134, UNIMEMSIZE, PSW_1134, + 0, PAR_1134, PDR_1134, MM0_1134, 0 }, + { "11/40", SOP_1140, OPT_1140, UNIMEMSIZE, PSW_1140, + 0, PAR_1140, PDR_1140, MM0_1140, 0 }, + { "11/44", SOP_1144, OPT_1144, MAXMEMSIZE, PSW_1144, + MFPT_44, PAR_1144, PDR_1144, MM0_1144, MM3_1144 }, + { "11/45", SOP_1145, OPT_1145, UNIMEMSIZE, PSW_1145, + 0, PAR_1145, PDR_1145, MM0_1145, MM3_1145 }, + { "11/60", SOP_1160, OPT_1160, UNIMEMSIZE, PSW_1160, + 0, PAR_1160, PDR_1160, MM0_1160, 0 }, + { "11/70", SOP_1170, OPT_1170, MAXMEMSIZE, PSW_1170, + 0, PAR_1170, PDR_1170, MM0_1170, MM3_1170 }, + { "11/73", SOP_1173, OPT_1173, MAXMEMSIZE, PSW_J, + MFPT_J, PAR_J, PDR_J, MM0_J, MM3_J }, + { "11/53", SOP_1153, OPT_1153, MAXMEMSIZE, PSW_J, + MFPT_J, PAR_J, PDR_J, MM0_J, MM3_J }, + { "11/73B", SOP_1173B, OPT_1173B, MAXMEMSIZE, PSW_J, + MFPT_J, PAR_J, PDR_J, MM0_J, MM3_J }, + { "11/83", SOP_1183, OPT_1183, MAXMEMSIZE, PSW_J, + MFPT_J, PAR_J, PDR_J, MM0_J, MM3_J }, + { "11/84", SOP_1184, OPT_1184, MAXMEMSIZE, PSW_J, + MFPT_J, PAR_J, PDR_J, MM0_J, MM3_J }, + { "11/93", SOP_1193, OPT_1193, MAXMEMSIZE, PSW_J, + MFPT_J, PAR_J, PDR_J, MM0_J, MM3_J }, + { "11/94", SOP_1194, OPT_1194, MAXMEMSIZE, PSW_J, + MFPT_J, PAR_J, PDR_J, MM0_J, MM3_J } + }; CNFTAB cnf_tab[] = { - { HAS_PSW, 0, &psw_dib }, /* PSW */ - { CPUT_J, 0, &cpuj_dib }, /* CPU control */ - { CPUT_24, 0, &cpu24_dib }, - { CPUT_44, 0, &cpu44_dib }, - { CPUT_45, 0, &cpu45_dib }, - { CPUT_60, 0, &cpu60_dib }, - { CPUT_70, 0, &cpu70_dib }, - { HAS_IOSR, 0, ®_dib }, - { CPUT_23P, 0, &ctlfb_dib }, /* board ctls */ - { CPUT_JB, 0, &ctljb_dib }, - { CPUT_53, 0, &ctljd_dib }, - { CPUT_JE, 0, &ctlje_dib }, - { CPUT_24, 0, &uba24_dib }, /* UBA */ - { CPUT_JU, 0, &ubaj_dib }, - { 0, OPT_MMU, &kipdr_dib }, /* MMU */ - { 0, OPT_MMU, &kipar_dib }, - { 0, OPT_MMU, &uipdr_dib }, - { 0, OPT_MMU, &uipar_dib }, - { 0, OPT_MMU, &mmr012_dib }, /* MMR0-2 */ - { HAS_MMR3, 0, &mmr3_dib }, /* MMR3 */ - { 0, OPT_UBM, &ubm_dib }, /* Unibus map */ - { HAS_SID, 0, &kdpdr_dib }, /* supv, I/D */ - { HAS_SID, 0, &kdpar_dib }, - { HAS_SID, 0, &supv_dib }, - { HAS_SID, 0, &udpdr_dib }, - { HAS_SID, 0, &udpar_dib }, - { HAS_SR, 0, &sr_dib }, /* SR */ - { HAS_DR, 0, &dr_dib }, /* DR */ - { 0, 0, NULL } }; + { HAS_PSW, 0, &psw_dib }, /* PSW */ + { CPUT_J, 0, &cpuj_dib }, /* CPU control */ + { CPUT_24, 0, &cpu24_dib }, + { CPUT_44, 0, &cpu44_dib }, + { CPUT_45, 0, &cpu45_dib }, + { CPUT_60, 0, &cpu60_dib }, + { CPUT_70, 0, &cpu70_dib }, + { HAS_IOSR, 0, ®_dib }, + { CPUT_23P, 0, &ctlfb_dib }, /* board ctls */ + { CPUT_JB, 0, &ctljb_dib }, + { CPUT_53, 0, &ctljd_dib }, + { CPUT_JE, 0, &ctlje_dib }, + { CPUT_24, 0, &uba24_dib }, /* UBA */ + { CPUT_JU, 0, &ubaj_dib }, + { 0, OPT_MMU, &kipdr_dib }, /* MMU */ + { 0, OPT_MMU, &kipar_dib }, + { 0, OPT_MMU, &uipdr_dib }, + { 0, OPT_MMU, &uipar_dib }, + { 0, OPT_MMU, &mmr012_dib }, /* MMR0-2 */ + { HAS_MMR3, 0, &mmr3_dib }, /* MMR3 */ + { 0, OPT_UBM, &ubm_dib }, /* Unibus map */ + { HAS_SID, 0, &kdpdr_dib }, /* supv, I/D */ + { HAS_SID, 0, &kdpar_dib }, + { HAS_SID, 0, &supv_dib }, + { HAS_SID, 0, &udpdr_dib }, + { HAS_SID, 0, &udpar_dib }, + { HAS_SR, 0, &sr_dib }, /* SR */ + { HAS_DR, 0, &dr_dib }, /* DR */ + { 0, 0, NULL } + }; static const char *opt_name[] = { - "Unibus", "Qbus", "EIS", "NOEIS", "FIS", "NOFIS", - "FPP", "NOFPP", "CIS", "NOCIS", "MMU", "NOMMU", - "RH11", "RH70", "PARITY", "NOPARITY", "Unibus map", "No map", NULL }; - + "Unibus", "Qbus", "EIS", "NOEIS", "FIS", "NOFIS", + "FPP", "NOFPP", "CIS", "NOCIS", "MMU", "NOMMU", + "RH11", "RH70", "PARITY", "NOPARITY", "Unibus map", "No map", NULL + }; + /* SYSTEM data structures - sys_dev SYSTEM device descriptor - sys_unit SYSTEM unit descriptor - sys_reg SYSTEM register list + sys_dev SYSTEM device descriptor + sys_unit SYSTEM unit descriptor + sys_reg SYSTEM register list */ UNIT sys_unit = { UDATA (NULL, 0, 0) }; REG sys_reg[] = { - { 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) }, - { ORDATA (MBRK, MBRK, 16) }, - { ORDATA (SYSID, SYSID, 16) }, - { ORDATA (JCSR, JCSR, 16) }, - { ORDATA (JPCR, JPCR, 16) }, - { ORDATA (JASR, JASR, 16) }, - { ORDATA (UDCR, UDCR, 16) }, - { ORDATA (UDDR, UDDR, 16) }, - { ORDATA (UCSR, UCSR, 16) }, - { ORDATA (ULAST, uba_last, 23) }, - { BRDATA (UBMAP, ub_map, 8, 22, UBM_LNT_LW) }, - { DRDATA (TOY_STATE, toy_state, 6), REG_HRO }, - { BRDATA (TOY_DATA, toy_data, 8, 8, TOY_LNT), REG_HRO }, - { NULL} }; + { 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) }, + { ORDATA (MBRK, MBRK, 16) }, + { ORDATA (WCS, WCS, 16) }, + { ORDATA (SYSID, SYSID, 16) }, + { ORDATA (JCSR, JCSR, 16) }, + { ORDATA (JPCR, JPCR, 16) }, + { ORDATA (JASR, JASR, 16) }, + { ORDATA (UDCR, UDCR, 16) }, + { ORDATA (UDDR, UDDR, 16) }, + { ORDATA (UCSR, UCSR, 16) }, + { ORDATA (ULAST, uba_last, 23) }, + { BRDATA (UBMAP, ub_map, 8, 22, UBM_LNT_LW) }, + { DRDATA (TOY_STATE, toy_state, 6), REG_HRO }, + { BRDATA (TOY_DATA, toy_data, 8, 8, TOY_LNT), REG_HRO }, + { NULL} + }; DEVICE sys_dev = { - "SYSTEM", &sys_unit, sys_reg, NULL, - 1, 0, 0, 0, 0, 0, - NULL, NULL, &sys_reset, - NULL, NULL, NULL, - NULL, 0, 0, - NULL, NULL, NULL }; - + "SYSTEM", &sys_unit, sys_reg, NULL, + 1, 0, 0, 0, 0, 0, + NULL, NULL, &sys_reset, + NULL, NULL, NULL, + NULL, 0, 0, + NULL, NULL, NULL + }; + /* Switch and display registers - many */ t_stat SR_rd (int32 *data, int32 pa, int32 access) @@ -310,317 +319,430 @@ return SCPE_OK; t_stat CPU24_rd (int32 *data, int32 pa, int32 access) { -switch ((pa >> 1) & 017) { /* decode pa<4:1> */ -case 013: /* CPUERR */ - *data = 0; - return SCPE_OK; } /* end switch PA */ +switch ((pa >> 1) & 017) { /* decode pa<4:1> */ + + case 013: /* CPUERR */ + *data = 0; + return SCPE_OK; + } /* end switch PA */ + *data = 0; -return SCPE_NXM; /* unimplemented */ +return SCPE_NXM; /* unimplemented */ } t_stat CPU24_wr (int32 data, int32 pa, int32 access) { -switch ((pa >> 1) & 017) { /* decode pa<4:1> */ -case 013: /* CPUERR */ - return SCPE_OK; } /* end switch pa */ -return SCPE_NXM; /* unimplemented */ +switch ((pa >> 1) & 017) { /* decode pa<4:1> */ + + case 013: /* CPUERR */ + return SCPE_OK; + } /* end switch pa */ + +return SCPE_NXM; /* unimplemented */ } /* CPU control registers - 11/44 */ t_stat CPU44_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 & CCR44_RD; - return SCPE_OK; -case 4: /* MAINT */ - *data = MAINT & CMR44_RD; - return SCPE_OK; -case 5: /* Hit/miss */ - *data = HITMISS; - return SCPE_OK; -case 6: /* CDR */ - *data = 0; - return SCPE_OK; -case 013: /* CPUERR */ - if (CPUERR & CPUE_YEL) /* 11/44 stack err */ - CPUERR = (CPUERR & ~CPUE_YEL) | CPUE_RED; /* in <2> not <3> */ - if (CPUERR & (CPUE_ODD|CPUE_NXM|CPUE_TMO)) /* additional flag */ - CPUERR = CPUERR | CPUE44_BUSE; - *data = CPUERR & CPUE_IMP; - return SCPE_OK; -case 015: /* PIRQ */ - *data = PIRQ; - return SCPE_OK; } /* end switch PA */ +switch ((pa >> 1) & 017) { /* decode pa<4:1> */ + + case 002: /* MEMERR */ + *data = MEMERR; + return SCPE_OK; + + case 003: /* CCR */ + *data = CCR & CCR44_RD; + return SCPE_OK; + + case 004: /* MAINT */ + *data = MAINT & CMR44_RD; + return SCPE_OK; + + case 005: /* Hit/miss */ + *data = HITMISS; + return SCPE_OK; + + case 006: /* CDR */ + *data = 0; + return SCPE_OK; + + case 013: /* CPUERR */ + if (CPUERR & CPUE_YEL) /* 11/44 stack err */ + CPUERR = (CPUERR & ~CPUE_YEL) | CPUE_RED; /* in <2> not <3> */ + if (CPUERR & (CPUE_ODD|CPUE_NXM|CPUE_TMO)) /* additional flag */ + CPUERR = CPUERR | CPUE44_BUSE; + *data = CPUERR & CPUE_IMP; + return SCPE_OK; + + case 015: /* PIRQ */ + *data = PIRQ; + return SCPE_OK; + } /* end switch PA */ + *data = 0; -return SCPE_NXM; /* unimplemented */ +return SCPE_NXM; /* unimplemented */ } t_stat CPU44_wr (int32 data, int32 pa, int32 access) { -switch ((pa >> 1) & 017) { /* decode pa<4:1> */ -case 2: /* MEMERR */ - MEMERR = 0; - return SCPE_OK; -case 3: /* CCR */ - ODD_MRG (CCR, data); - CCR = data & CCR44_WR; - return SCPE_OK; -case 4: /* MAINT */ - ODD_MRG (MAINT, data); - MAINT = data & CMR44_WR; - return SCPE_OK; -case 5: /* Hit/miss */ - return SCPE_OK; -case 013: /* CPUERR */ - CPUERR = 0; - return SCPE_OK; -case 015: /* PIRQ */ - ODD_WO (data); - put_PIRQ (data); - return SCPE_OK; } -return SCPE_NXM; /* unimplemented */ +switch ((pa >> 1) & 017) { /* decode pa<4:1> */ + + case 002: /* MEMERR */ + MEMERR = 0; + return SCPE_OK; + + case 003: /* CCR */ + ODD_MRG (CCR, data); + CCR = data & CCR44_WR; + return SCPE_OK; + + case 004: /* MAINT */ + ODD_MRG (MAINT, data); + MAINT = data & CMR44_WR; + return SCPE_OK; + + case 005: /* Hit/miss */ + return SCPE_OK; + + case 013: /* CPUERR */ + CPUERR = 0; + return SCPE_OK; + + case 015: /* PIRQ */ + ODD_WO (data); + put_PIRQ (data); + return SCPE_OK; + } + +return SCPE_NXM; /* unimplemented */ } - + /* CPU control registers - 11/45 */ t_stat CPU45_rd (int32 *data, int32 pa, int32 access) { -switch ((pa >> 1) & 017) { /* decode pa<4:1> */ -case 014: /* MBRK */ - *data = MBRK; - return SCPE_OK; -case 015: /* PIRQ */ - *data = PIRQ; - return SCPE_OK; -case 016: /* STKLIM */ - *data = STKLIM & STKLIM_RW; - return SCPE_OK; } /* end switch PA */ +switch ((pa >> 1) & 017) { /* decode pa<4:1> */ + + case 014: /* MBRK */ + *data = MBRK; + return SCPE_OK; + + case 015: /* PIRQ */ + *data = PIRQ; + return SCPE_OK; + + case 016: /* STKLIM */ + *data = STKLIM & STKLIM_RW; + return SCPE_OK; + } /* end switch PA */ + *data = 0; -return SCPE_NXM; /* unimplemented */ +return SCPE_NXM; /* unimplemented */ } t_stat CPU45_wr (int32 data, int32 pa, int32 access) { -switch ((pa >> 1) & 017) { /* decode pa<4:1> */ -case 015: /* PIRQ */ - ODD_WO (data); - put_PIRQ (data); - return SCPE_OK; -case 016: /* STKLIM */ - ODD_WO (data); - STKLIM = data & STKLIM_RW; - return SCPE_OK; } /* end switch pa */ -return SCPE_NXM; /* unimplemented */ +switch ((pa >> 1) & 017) { /* decode pa<4:1> */ + + case 015: /* PIRQ */ + ODD_WO (data); + put_PIRQ (data); + return SCPE_OK; + + case 016: /* STKLIM */ + ODD_WO (data); + STKLIM = data & STKLIM_RW; + return SCPE_OK; + } /* end switch pa */ + +return SCPE_NXM; /* unimplemented */ } - + /* CPU control registers - 11/60 */ t_stat CPU60_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 5: /* Hit/miss */ - *data = HITMISS; - return SCPE_OK; -case 016: /* STKLIM */ - *data = STKLIM & STKLIM_RW; - return SCPE_OK; } /* end switch PA */ +switch ((pa >> 1) & 017) { /* decode pa<4:1> */ + + case 000: /* WCS */ + *data = WCS & WCS60_RD; + return SCPE_OK; + + case 002: /* MEMERR */ + *data = MEMERR & MEME60_RD; + return SCPE_OK; + + case 003: /* CCR */ + *data = CCR & CCR60_RD; + return SCPE_OK; + + case 005: /* Hit/miss */ + *data = HITMISS; + return SCPE_OK; + + case 013: /* CPUERR */ + if (CPUERR & CPUE_NXM) /* TMO only */ + CPUERR = (CPUERR & ~CPUE_NXM) | CPUE_TMO; + *data = CPUERR & CPUE60_RD; + return SCPE_OK; + + case 016: /* STKLIM */ + *data = STKLIM & STKLIM_RW; + return SCPE_OK; + } /* end switch PA */ + *data = 0; -return SCPE_NXM; /* unimplemented */ +return SCPE_NXM; /* unimplemented */ } t_stat CPU60_wr (int32 data, int32 pa, int32 access) { -switch ((pa >> 1) & 017) { /* decode pa<4:1> */ -case 2: /* MEMERR */ - MEMERR = 0; - return SCPE_OK; -case 3: /* CCR */ - ODD_MRG (CCR, data); - CCR = data; - return SCPE_OK; -case 5: /* Hit/miss */ - return SCPE_OK; -case 016: /* STKLIM */ - ODD_WO (data); - STKLIM = data & STKLIM_RW; - return SCPE_OK; } /* end switch pa */ -return SCPE_NXM; /* unimplemented */ +switch ((pa >> 1) & 017) { /* decode pa<4:1> */ + + case 000: /* WCS */ + WCS = data & WCS60_WR; + return SCPE_OK; + + case 002: /* MEMERR */ + MEMERR = 0; + return SCPE_OK; + + case 003: /* CCR */ + ODD_IGN (data); + CCR = data & CCR60_WR; + return SCPE_OK; + + case 005: /* Hit/miss */ + return SCPE_OK; + + case 013: /* CPUERR */ + CPUERR = 0; + return SCPE_OK; + + case 014: /* MBRK */ + MBRK = data & MBRK60_WR; + return SCPE_OK; + + case 016: /* STKLIM */ + ODD_WO (data); + STKLIM = data & STKLIM_RW; + return SCPE_OK; + } /* end switch pa */ + +return SCPE_NXM; /* unimplemented */ } - + /* CPU control registers - 11/70 */ t_stat CPU70_rd (int32 *data, int32 pa, int32 access) { -switch ((pa >> 1) & 017) { /* decode pa<4:1> */ -case 0: case 1: case 011: /* LO,HI ERR, HI SIZE */ - *data = 0; - return SCPE_OK; -case 2: /* MEMERR */ - *data = MEMERR; - return SCPE_OK; -case 3: /* CCR */ - *data = CCR; - return SCPE_OK; -case 4: /* MAINT */ - *data = 0; - return SCPE_OK; -case 5: /* Hit/miss */ - *data = HITMISS; - return SCPE_OK; -case 010: /* lower size */ - *data = (MEMSIZE >> 6) - 1; - return SCPE_OK; -case 012: /* system ID */ - *data = SYSID; - return SCPE_OK; -case 013: /* CPUERR */ - *data = CPUERR & CPUE_IMP; - return SCPE_OK; -case 014: /* MBRK */ - *data = MBRK; - return SCPE_OK; -case 015: /* PIRQ */ - *data = PIRQ; - return SCPE_OK; -case 016: /* STKLIM */ - *data = STKLIM & STKLIM_RW; - return SCPE_OK; } /* end switch PA */ +switch ((pa >> 1) & 017) { /* decode pa<4:1> */ + + case 000: case 001: case 011: /* LO,HI ERR, HI SIZE */ + *data = 0; + return SCPE_OK; + + case 002: /* MEMERR */ + *data = MEMERR; + return SCPE_OK; + + case 003: /* CCR */ + *data = CCR; + return SCPE_OK; + + case 004: /* MAINT */ + *data = 0; + return SCPE_OK; + + case 005: /* Hit/miss */ + *data = HITMISS; + return SCPE_OK; + + case 010: /* lower size */ + *data = (MEMSIZE >> 6) - 1; + return SCPE_OK; + + case 012: /* system ID */ + *data = SYSID; + return SCPE_OK; + + case 013: /* CPUERR */ + *data = CPUERR & CPUE_IMP; + return SCPE_OK; + + case 014: /* MBRK */ + *data = MBRK; + return SCPE_OK; + + case 015: /* PIRQ */ + *data = PIRQ; + return SCPE_OK; + + case 016: /* STKLIM */ + *data = STKLIM & STKLIM_RW; + return SCPE_OK; + } /* end switch PA */ + *data = 0; -return SCPE_NXM; /* unimplemented */ +return SCPE_NXM; /* unimplemented */ } t_stat CPU70_wr (int32 data, int32 pa, int32 access) { -switch ((pa >> 1) & 017) { /* decode pa<4:1> */ -case 2: /* MEMERR */ - ODD_WO (data); - MEMERR = MEMERR & ~data; - return SCPE_OK; -case 3: /* CCR */ - ODD_MRG (CCR, 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 014: /* MBRK */ - MBRK = data; - return SCPE_OK; -case 015: /* PIRQ */ - ODD_WO (data); - put_PIRQ (data); - return SCPE_OK; -case 016: /* STKLIM */ - ODD_WO (data); - STKLIM = data & STKLIM_RW; - return SCPE_OK; } /* end switch pa */ -return SCPE_NXM; /* unimplemented */ +switch ((pa >> 1) & 017) { /* decode pa<4:1> */ + + case 002: /* MEMERR */ + ODD_WO (data); + MEMERR = MEMERR & ~data; + return SCPE_OK; + + case 003: /* CCR */ + ODD_MRG (CCR, data); + CCR = data; + return SCPE_OK; + + case 004: /* MAINT */ + return SCPE_OK; + + case 005: /* Hit/miss */ + return SCPE_OK; + + case 013: /* CPUERR */ + CPUERR = 0; + return SCPE_OK; + + case 014: /* MBRK */ + MBRK = data; + return SCPE_OK; + + case 015: /* PIRQ */ + ODD_WO (data); + put_PIRQ (data); + return SCPE_OK; + + case 016: /* STKLIM */ + ODD_WO (data); + STKLIM = data & STKLIM_RW; + return SCPE_OK; + } /* end switch pa */ + +return SCPE_NXM; /* unimplemented */ } - + /* CPU control registers - J11 */ t_stat CPUJ_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 */ - *data = MAINT | MAINT_NOFPA | MAINT_BPOK | (UNIBUS? MAINT_U: MAINT_Q); - if (CPUT (CPUT_53)) *data |= MAINT_KDJD | MAINT_POROM; - if (CPUT (CPUT_73)) *data |= MAINT_KDJA | MAINT_POODT; - if (CPUT (CPUT_73B|CPUT_83|CPUT_84)) *data |= MAINT_KDJB | MAINT_POROM; - if (CPUT (CPUT_93|CPUT_94)) *data |= MAINT_KDJE | MAINT_POROM; - return SCPE_OK; -case 5: /* Hit/miss */ - if (CPUT (CPUT_73B)) *data = 0; /* must be 0 for 73B */ - else *data = HITMISS | 010; /* must be nz for 11/8X */ - return SCPE_OK; -case 013: /* CPUERR */ - *data = CPUERR & CPUE_IMP; - return SCPE_OK; -case 015: /* PIRQ */ - *data = PIRQ; - return SCPE_OK; } /* end switch PA */ +switch ((pa >> 1) & 017) { /* decode pa<4:1> */ + + case 002: /* MEMERR */ + *data = MEMERR; + return SCPE_OK; + + case 003: /* CCR */ + *data = CCR; + return SCPE_OK; + + case 004: /* MAINT */ + *data = MAINT | MAINT_NOFPA | MAINT_BPOK | (UNIBUS? MAINT_U: MAINT_Q); + if (CPUT (CPUT_53)) *data |= MAINT_KDJD | MAINT_POROM; + if (CPUT (CPUT_73)) *data |= MAINT_KDJA | MAINT_POODT; + if (CPUT (CPUT_73B|CPUT_83|CPUT_84)) *data |= MAINT_KDJB | MAINT_POROM; + if (CPUT (CPUT_93|CPUT_94)) *data |= MAINT_KDJE | MAINT_POROM; + return SCPE_OK; + + case 005: /* Hit/miss */ + if (CPUT (CPUT_73B)) *data = 0; /* must be 0 for 73B */ + else *data = HITMISS | 010; /* must be nz for 11/8X */ + return SCPE_OK; + + case 013: /* CPUERR */ + *data = CPUERR & CPUE_IMP; + return SCPE_OK; + + case 015: /* PIRQ */ + *data = PIRQ; + return SCPE_OK; + } /* end switch PA */ + *data = 0; -return SCPE_NXM; /* unimplemented */ +return SCPE_NXM; /* unimplemented */ } t_stat CPUJ_wr (int32 data, int32 pa, int32 access) { -switch ((pa >> 1) & 017) { /* decode pa<4:1> */ -case 2: /* MEMERR */ - MEMERR = 0; - return SCPE_OK; -case 3: /* CCR */ - ODD_MRG (CCR, 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 */ - ODD_WO (data); - put_PIRQ (data); - return SCPE_OK; } /* end switch pa */ -return SCPE_NXM; /* unimplemented */ +switch ((pa >> 1) & 017) { /* decode pa<4:1> */ + + case 002: /* MEMERR */ + MEMERR = 0; + return SCPE_OK; + + case 003: /* CCR */ + ODD_MRG (CCR, data); + CCR = data; + return SCPE_OK; + + case 004: /* MAINT */ + return SCPE_OK; + + case 005: /* Hit/miss */ + return SCPE_OK; + + case 013: /* CPUERR */ + CPUERR = 0; + return SCPE_OK; + + case 015: /* PIRQ */ + ODD_WO (data); + put_PIRQ (data); + return SCPE_OK; + } /* end switch pa */ + +return SCPE_NXM; /* unimplemented */ } - + /* Board control registers - KDF11B */ t_stat CTLFB_rd (int32 *data, int32 pa, int32 access) { -switch ((pa >> 1) & 03) { /* decode pa<2:1> */ -case 0: /* PCR */ - *data = JPCR & PCRFB_RW; - return SCPE_OK; -case 1: /* MAINT */ - *data = MAINT; - return SCPE_OK; -case 2: /* CDR */ - *data = SR & CDRFB_RD; - return SCPE_OK; } +switch ((pa >> 1) & 03) { /* decode pa<2:1> */ + + case 0: /* PCR */ + *data = JPCR & PCRFB_RW; + return SCPE_OK; + + case 1: /* MAINT */ + *data = MAINT; + return SCPE_OK; + + case 2: /* CDR */ + *data = SR & CDRFB_RD; + return SCPE_OK; + } + *data = 0; return SCPE_NXM; } t_stat CTLFB_wr (int32 data, int32 pa, int32 access) { -switch ((pa >> 1) & 03) { /* decode pa<2:1> */ -case 0: /* PCR */ - ODD_MRG (JPCR, data); - JPCR = data & PCRFB_RW; - return SCPE_OK; -case 1: /* MAINT */ - ODD_MRG (MAINT, data); - MAINT = data; - return SCPE_OK; -case 2: /* CDR */ - ODD_WO (data); - DR = data & CDRFB_WR; - return SCPE_OK; } +switch ((pa >> 1) & 03) { /* decode pa<2:1> */ + + case 0: /* PCR */ + ODD_MRG (JPCR, data); + JPCR = data & PCRFB_RW; + return SCPE_OK; + case 1: /* MAINT */ + ODD_MRG (MAINT, data); + MAINT = data; + return SCPE_OK; + case 2: /* CDR */ + ODD_WO (data); + DR = data & CDRFB_WR; + return SCPE_OK; + } + return SCPE_NXM; } @@ -628,16 +750,21 @@ return SCPE_NXM; t_stat CTLJB_rd (int32 *data, int32 pa, int32 access) { -switch ((pa >> 1) & 03) { /* decode pa<2:1> */ -case 0: /* CSR */ - *data = JCSR & CSRJB_RD; - return SCPE_OK; -case 1: /* PCR */ - *data = JPCR & PCRJB_RW; - return SCPE_OK; -case 2: /* CDR */ - *data = SR & CDRJB_RD; - return SCPE_OK; } +switch ((pa >> 1) & 03) { /* decode pa<2:1> */ + + case 0: /* CSR */ + *data = JCSR & CSRJB_RD; + return SCPE_OK; + + case 1: /* PCR */ + *data = JPCR & PCRJB_RW; + return SCPE_OK; + + case 2: /* CDR */ + *data = SR & CDRJB_RD; + return SCPE_OK; + } + *data = 0; return SCPE_NXM; } @@ -646,26 +773,31 @@ t_stat CTLJB_wr (int32 data, int32 pa, int32 access) { int32 t; -switch ((pa >> 1) & 03) { /* decode pa<2:1> */ -case 0: /* CSR */ - ODD_MRG (JCSR, data); - JCSR = (JCSR & ~CSRJB_WR) | (data & CSRJB_WR); - if (JCSR & CSRJ_LTCI) clk_fie = 1; /* force LTC int enb? */ - else clk_fie = 0; - if (JCSR & CSRJ_LTCD) clk_fnxm = 1; /* force LTC reg nxm? */ - else clk_fnxm = 0; - t = CSRJ_LTCSEL (JCSR); /* get freq sel */ - if (t) clk_tps = clk_tps_map[t]; - else clk_tps = clk_default; - return SCPE_OK; -case 1: /* PCR */ - ODD_MRG (JPCR, data); - JPCR = data & PCRJB_RW; - return SCPE_OK; -case 2: /* CDR */ - ODD_WO (data); - DR = data & CDRJB_WR; - return SCPE_OK; } +switch ((pa >> 1) & 03) { /* decode pa<2:1> */ + + case 0: /* CSR */ + ODD_MRG (JCSR, data); + JCSR = (JCSR & ~CSRJB_WR) | (data & CSRJB_WR); + if (JCSR & CSRJ_LTCI) clk_fie = 1; /* force LTC int enb? */ + else clk_fie = 0; + if (JCSR & CSRJ_LTCD) clk_fnxm = 1; /* force LTC reg nxm? */ + else clk_fnxm = 0; + t = CSRJ_LTCSEL (JCSR); /* get freq sel */ + if (t) clk_tps = clk_tps_map[t]; + else clk_tps = clk_default; + return SCPE_OK; + + case 1: /* PCR */ + ODD_MRG (JPCR, data); + JPCR = data & PCRJB_RW; + return SCPE_OK; + + case 2: /* CDR */ + ODD_WO (data); + DR = data & CDRJB_WR; + return SCPE_OK; + } + return SCPE_NXM; } @@ -673,21 +805,27 @@ return SCPE_NXM; t_stat CTLJD_rd (int32 *data, int32 pa, int32 access) { -switch ((pa >> 1) & 03) { /* decode pa<2:1> */ -case 0: /* CSR */ - *data = JCSR & CSRJD_RD; - return SCPE_OK; } +switch ((pa >> 1) & 03) { /* decode pa<2:1> */ + + case 0: /* CSR */ + *data = JCSR & CSRJD_RD; + return SCPE_OK; + } + *data = 0; return SCPE_NXM; } t_stat CTLJD_wr (int32 data, int32 pa, int32 access) { -switch ((pa >> 1) & 03) { /* decode pa<2:1> */ -case 0: /* CSR */ - ODD_MRG (JCSR, data); - JCSR = (JCSR & ~CSRJD_WR) | (data & CSRJD_WR); - return SCPE_OK; } +switch ((pa >> 1) & 03) { /* decode pa<2:1> */ + + case 0: /* CSR */ + ODD_MRG (JCSR, data); + JCSR = (JCSR & ~CSRJD_WR) | (data & CSRJD_WR); + return SCPE_OK; + } + return SCPE_NXM; } @@ -695,20 +833,26 @@ return SCPE_NXM; t_stat CTLJE_rd (int32 *data, int32 pa, int32 access) { -switch ((pa >> 1) & 03) { /* decode pa<2:1> */ -case 0: /* CSR */ - *data = JCSR & CSRJE_RD; - return SCPE_OK; -case 1: /* PCR */ - *data = JPCR & PCRJE_RW; - return SCPE_OK; -case 2: /* CDR */ - *data = SR & CDRJE_RD; - return SCPE_OK; -case 3: /* ASR */ - JASR = (JASR & ~ASRJE_TOY) | (toy_read () << ASRJE_V_TOY); - *data = JASR & ASRJE_RW; - return SCPE_OK; } +switch ((pa >> 1) & 03) { /* decode pa<2:1> */ + + case 0: /* CSR */ + *data = JCSR & CSRJE_RD; + return SCPE_OK; + + case 1: /* PCR */ + *data = JPCR & PCRJE_RW; + return SCPE_OK; + + case 2: /* CDR */ + *data = SR & CDRJE_RD; + return SCPE_OK; + + case 3: /* ASR */ + JASR = (JASR & ~ASRJE_TOY) | (toy_read () << ASRJE_V_TOY); + *data = JASR & ASRJE_RW; + return SCPE_OK; + } + *data = 0; return SCPE_NXM; } @@ -717,56 +861,68 @@ t_stat CTLJE_wr (int32 data, int32 pa, int32 access) { int32 t; -switch ((pa >> 1) & 03) { /* decode pa<2:1> */ -case 0: /* CSR */ - ODD_MRG (JCSR, data); - JCSR = (JCSR & ~CSRJE_WR) | (data & CSRJE_WR); - if (JCSR & CSRJ_LTCI) clk_fie = 1; /* force LTC int enb? */ - else clk_fie = 0; - if (JCSR & CSRJ_LTCD) clk_fnxm = 1; /* force LTC reg nxm? */ - else clk_fnxm = 0; - t = CSRJ_LTCSEL (JCSR); /* get freq sel */ - if (t) clk_tps = clk_tps_map[t]; - else clk_tps = clk_default; - return SCPE_OK; -case 1: /* PCR */ - ODD_MRG (JPCR, data); - JPCR = data & PCRJE_RW; - return SCPE_OK; -case 2: /* CDR */ - ODD_WO (data); - DR = data & CDRJE_WR; - return SCPE_OK; -case 3: /* ASR */ - ODD_MRG (JASR, data); - JASR = data & ASRJE_RW; - toy_write (ASRJE_TOYBIT (JASR)); - return SCPE_OK; } +switch ((pa >> 1) & 03) { /* decode pa<2:1> */ + + case 0: /* CSR */ + ODD_MRG (JCSR, data); + JCSR = (JCSR & ~CSRJE_WR) | (data & CSRJE_WR); + if (JCSR & CSRJ_LTCI) clk_fie = 1; /* force LTC int enb? */ + else clk_fie = 0; + if (JCSR & CSRJ_LTCD) clk_fnxm = 1; /* force LTC reg nxm? */ + else clk_fnxm = 0; + t = CSRJ_LTCSEL (JCSR); /* get freq sel */ + if (t) clk_tps = clk_tps_map[t]; + else clk_tps = clk_default; + return SCPE_OK; + + case 1: /* PCR */ + ODD_MRG (JPCR, data); + JPCR = data & PCRJE_RW; + return SCPE_OK; + + case 2: /* CDR */ + ODD_WO (data); + DR = data & CDRJE_WR; + return SCPE_OK; + + case 3: /* ASR */ + ODD_MRG (JASR, data); + JASR = data & ASRJE_RW; + toy_write (ASRJE_TOYBIT (JASR)); + return SCPE_OK; + } + return SCPE_NXM; } - + /* Unibus adapter registers - KT24 */ t_stat UBA24_rd (int32 *data, int32 pa, int32 access) { -switch ((pa >> 1) & 03) { /* decode pa<2:1> */ -case 2: /* LMAL */ - *data = uba_last & LMAL_RD; - return SCPE_OK; -case 3: /* LMAH */ - *data = uba_last & LMAH_RD; - return SCPE_OK; } +switch ((pa >> 1) & 03) { /* decode pa<2:1> */ + + case 2: /* LMAL */ + *data = uba_last & LMAL_RD; + return SCPE_OK; + case 3: /* LMAH */ + *data = uba_last & LMAH_RD; + return SCPE_OK; + } + *data = 0; return SCPE_NXM; } t_stat UBA24_wr (int32 data, int32 pa, int32 access) { -switch ((pa >> 1) & 03) { /* decode pa<2:1> */ -case 3: /* ASR */ - ODD_IGN (data); - uba_last = (uba_last & ~LMAH_WR) | ((data & LMAH_WR) << 16); - return SCPE_OK; } +switch ((pa >> 1) & 03) { /* decode pa<2:1> */ + + case 3: /* ASR */ + ODD_IGN (data); + uba_last = (uba_last & ~LMAH_WR) | ((data & LMAH_WR) << 16); + return SCPE_OK; + } + return SCPE_NXM; } @@ -774,38 +930,48 @@ return SCPE_NXM; t_stat UBAJ_rd (int32 *data, int32 pa, int32 access) { -switch ((pa >> 1) & 03) { /* decode pa<2:1> */ -case 0: /* DCR */ - *data = UDCR & DCRKTJ_RD; - return SCPE_OK; -case 1: /* DDR */ - *data = UDDR & DDRKTJ_RW; - return SCPE_OK; -case 2: /* CSR */ - *data = UCSR & MCRKTJ_RD; - return SCPE_OK; } +switch ((pa >> 1) & 03) { /* decode pa<2:1> */ + + case 0: /* DCR */ + *data = UDCR & DCRKTJ_RD; + return SCPE_OK; + + case 1: /* DDR */ + *data = UDDR & DDRKTJ_RW; + return SCPE_OK; + + case 2: /* CSR */ + *data = UCSR & MCRKTJ_RD; + return SCPE_OK; + } + *data = 0; return SCPE_NXM; } t_stat UBAJ_wr (int32 data, int32 pa, int32 access) { -switch ((pa >> 1) & 03) { /* decode pa<2:1> */ -case 0: /* DCR */ - ODD_MRG (UDCR, data); - UDCR = (UDCR & ~DCRKTJ_WR) | (data & DCRKTJ_WR); - return SCPE_OK; -case 1: /* DDR */ - ODD_MRG (UDDR, data); - UDDR = data & DDRKTJ_RW;; - return SCPE_OK; -case 2: /* CSR */ - ODD_MRG (UCSR, data); - UCSR = (UCSR & ~MCRKTJ_WR) | (data & MCRKTJ_WR); - return SCPE_OK; } +switch ((pa >> 1) & 03) { /* decode pa<2:1> */ + + case 0: /* DCR */ + ODD_MRG (UDCR, data); + UDCR = (UDCR & ~DCRKTJ_WR) | (data & DCRKTJ_WR); + return SCPE_OK; + + case 1: /* DDR */ + ODD_MRG (UDDR, data); + UDDR = data & DDRKTJ_RW;; + return SCPE_OK; + + case 2: /* CSR */ + ODD_MRG (UCSR, data); + UCSR = (UCSR & ~MCRKTJ_WR) | (data & MCRKTJ_WR); + return SCPE_OK; + } + return SCPE_NXM; } - + /* KDJ11E TOY routines */ int32 toy_read (void) @@ -815,18 +981,19 @@ struct tm *ctm; int32 bit; if (toy_state == 0) { - curr = time (NULL); /* get curr time */ - if (curr == (time_t) -1) return 0; /* error? */ - ctm = localtime (&curr); /* decompose */ - if (ctm == NULL) return 0; /* error? */ - toy_data[TOY_HSEC] = 0x50; - toy_data[TOY_SEC] = toy_set (ctm->tm_sec); - toy_data[TOY_MIN] = toy_set (ctm->tm_min); - toy_data[TOY_HR] = toy_set (ctm->tm_hour); - toy_data[TOY_DOW] = toy_set (ctm->tm_wday); - toy_data[TOY_DOM] = toy_set (ctm->tm_mday); - toy_data[TOY_MON] = toy_set (ctm->tm_mon + 1); - toy_data[TOY_YR] = toy_set (ctm->tm_year % 100); } + curr = time (NULL); /* get curr time */ + if (curr == (time_t) -1) return 0; /* error? */ + ctm = localtime (&curr); /* decompose */ + if (ctm == NULL) return 0; /* error? */ + toy_data[TOY_HSEC] = 0x50; + toy_data[TOY_SEC] = toy_set (ctm->tm_sec); + toy_data[TOY_MIN] = toy_set (ctm->tm_min); + toy_data[TOY_HR] = toy_set (ctm->tm_hour); + toy_data[TOY_DOW] = toy_set (ctm->tm_wday); + toy_data[TOY_DOM] = toy_set (ctm->tm_mday); + toy_data[TOY_MON] = toy_set (ctm->tm_mon + 1); + toy_data[TOY_YR] = toy_set (ctm->tm_year % 100); + } bit = toy_data[toy_state >> 3] >> (toy_state & 07); toy_state = (toy_state + 1) % (TOY_LNT * 8); return (bit & 1); @@ -846,7 +1013,7 @@ d1 = val / 10; d2 = val % 10; return (uint8) ((d1 << 4) | d2); } - + /* Build I/O space entries for CPU */ t_stat cpu_build_dib (void) @@ -854,13 +1021,13 @@ t_stat cpu_build_dib (void) int32 i; t_stat r; -for (i = 0; cnf_tab[i].dib != NULL; i++) { /* loop thru config tab */ - if (((cnf_tab[i].cpum == 0) || (cpu_type & cnf_tab[i].cpum)) && - ((cnf_tab[i].optm == 0) || (cpu_opt & cnf_tab[i].optm))) { - if (r = build_ubus_tab (&cpu_dev, cnf_tab[i].dib)) /* add to dispatch tab */ - return r; - } - } +for (i = 0; cnf_tab[i].dib != NULL; i++) { /* loop thru config tab */ + if (((cnf_tab[i].cpum == 0) || (cpu_type & cnf_tab[i].cpum)) && + ((cnf_tab[i].optm == 0) || (cpu_opt & cnf_tab[i].optm))) { + if (r = build_ubus_tab (&cpu_dev, cnf_tab[i].dib)) /* add to dispatch tab */ + return r; + } + } return SCPE_OK; } @@ -872,13 +1039,13 @@ if (cptr != NULL) return SCPE_ARG; if (val >= MOD_MAX) return SCPE_IERR; if (val == (int32) cpu_model) return SCPE_OK; if (MEMSIZE > cpu_tab[val].maxm) - cpu_set_size (uptr, cpu_tab[val].maxm, NULL, NULL); + cpu_set_size (uptr, cpu_tab[val].maxm, NULL, NULL); if (MEMSIZE > cpu_tab[val].maxm) return SCPE_INCOMP; cpu_model = val; cpu_type = 1u << cpu_model; cpu_opt = cpu_tab[cpu_model].std; cpu_set_bus (cpu_opt); -reset_all (0); /* reset world */ +reset_all (0); /* reset world */ return SCPE_OK; } @@ -889,9 +1056,9 @@ uint32 i, all_opt; fprintf (st, "%s", cpu_tab[cpu_model].name); all_opt = cpu_tab[cpu_model].opt; for (i = 0; opt_name[2 * i] != NULL; i++) { - if ((all_opt >> i) & 1) fprintf (st, ", %s", - ((cpu_opt >> i) & 1)? opt_name[2 * i]: opt_name[(2 * i) + 1]); - } + if ((all_opt >> i) & 1) fprintf (st, ", %s", + ((cpu_opt >> i) & 1)? opt_name[2 * i]: opt_name[(2 * i) + 1]); + } return SCPE_OK; } @@ -922,11 +1089,11 @@ uint32 i, clim; uint16 *nM; if ((val <= 0) || (val > (int32) cpu_tab[cpu_model].maxm) || - ((val & 07777) != 0)) return SCPE_ARG; + ((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 (uint16)); + return SCPE_OK; +nM = (uint16 *) calloc (val >> 1, sizeof (uint16)); 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]; @@ -944,17 +1111,19 @@ t_stat cpu_set_bus (int32 opt) DEVICE *dptr; uint32 i, mask; -if (opt & BUS_U) mask = DEV_UBUS; /* Unibus variant? */ -else if (MEMSIZE <= UNIMEMSIZE) /* 18b Qbus devices? */ - mask = DEV_QBUS | DEV_Q18; -else mask = DEV_QBUS; /* must be 22b */ +if (opt & BUS_U) mask = DEV_UBUS; /* Unibus variant? */ +else if (MEMSIZE <= UNIMEMSIZE) /* 18b Qbus devices? */ + mask = DEV_QBUS | DEV_Q18; +else mask = DEV_QBUS; /* must be 22b */ for (i = 0; (dptr = sim_devices[i]) != NULL; i++) { - if ((dptr->flags & DEV_DISABLE) && /* disable-able? */ - !(dptr->flags & DEV_DIS) && /* enabled? */ - ((dptr->flags & mask) == 0)) { /* not allowed? */ - 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; } } + if ((dptr->flags & DEV_DISABLE) && /* disable-able? */ + !(dptr->flags & DEV_DIS) && /* enabled? */ + ((dptr->flags & mask) == 0)) { /* not allowed? */ + 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; } @@ -970,6 +1139,7 @@ CPUERR = 0; MEMERR = 0; if (!CPUT (CPUT_J)) MAINT = 0; MBRK = 0; +WCS = 0; JCSR = 0; JPCR = 0; JASR = 0; diff --git a/PDP11/pdp11_cpumod.h b/PDP11/pdp11_cpumod.h index feeb3d60..d5297d24 100644 --- a/PDP11/pdp11_cpumod.h +++ b/PDP11/pdp11_cpumod.h @@ -1,6 +1,6 @@ /* pdp11_cpumod.h: PDP-11 CPU model definitions - Copyright (c) 2004, Robert M Supnik + Copyright (c) 2004-2005, 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"), @@ -19,252 +19,268 @@ 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 + 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-05 RMS Added additional 11/60 registers */ #ifndef _PDP11_CPUMOD_H_ -#define _PDP11_CPUMOD_H_ 1 +#define _PDP11_CPUMOD_H_ 0 -#define SOP_1103 (BUS_Q) -#define OPT_1103 (OPT_EIS|OPT_FIS) -#define PSW_1103 0000377 +#define SOP_1103 (BUS_Q) +#define OPT_1103 (OPT_EIS|OPT_FIS) +#define PSW_1103 0000377 -#define SOP_1104 (BUS_U) -#define OPT_1104 0 -#define PSW_1104 0000377 +#define SOP_1104 (BUS_U) +#define OPT_1104 0 +#define PSW_1104 0000377 -#define SOP_1105 (BUS_U) -#define OPT_1105 0 -#define PSW_1105 0000377 +#define SOP_1105 (BUS_U) +#define OPT_1105 0 +#define PSW_1105 0000377 -#define SOP_1120 (BUS_U) -#define OPT_1120 0 -#define PSW_1120 0000377 +#define SOP_1120 (BUS_U) +#define OPT_1120 0 +#define PSW_1120 0000377 -#define SOP_1123 (BUS_Q|OPT_EIS|OPT_FPP|OPT_MMU) -#define OPT_1123 (OPT_FPP|OPT_CIS) -#define PSW_F 0170777 -#define PAR_F 0177777 -#define PDR_F 0077516 -#define MM0_F 0160157 -#define MM3_F 0000060 +#define SOP_1123 (BUS_Q|OPT_EIS|OPT_FPP|OPT_MMU) +#define OPT_1123 (OPT_FPP|OPT_CIS) +#define PSW_F 0170777 +#define PAR_F 0177777 +#define PDR_F 0077516 +#define MM0_F 0160157 +#define MM3_F 0000060 -#define SOP_1123P (BUS_Q|OPT_EIS|OPT_FPP|OPT_MMU) -#define OPT_1123P (OPT_FPP|OPT_CIS) +#define SOP_1123P (BUS_Q|OPT_EIS|OPT_FPP|OPT_MMU) +#define OPT_1123P (OPT_FPP|OPT_CIS) -#define SOP_1124 (BUS_U|OPT_EIS|OPT_FPP|OPT_MMU|OPT_UBM) -#define OPT_1124 (OPT_FPP|OPT_CIS) +#define SOP_1124 (BUS_U|OPT_EIS|OPT_FPP|OPT_MMU|OPT_UBM) +#define OPT_1124 (OPT_FPP|OPT_CIS) -#define SOP_1134 (BUS_U|OPT_EIS|OPT_MMU) -#define OPT_1134 (OPT_FPP) -#define PSW_1134 0170377 -#define PAR_1134 0007777 -#define PDR_1134 0077516 -#define MM0_1134 0160557 +#define SOP_1134 (BUS_U|OPT_EIS|OPT_MMU) +#define OPT_1134 (OPT_FPP) +#define PSW_1134 0170377 +#define PAR_1134 0007777 +#define PDR_1134 0077516 +#define MM0_1134 0160557 -#define SOP_1140 (BUS_U|OPT_EIS|OPT_MMU) -#define OPT_1140 (OPT_FIS) -#define PSW_1140 0170377 -#define PAR_1140 0007777 -#define PDR_1140 0077516 -#define MM0_1140 0160557 +#define SOP_1140 (BUS_U|OPT_EIS|OPT_MMU) +#define OPT_1140 (OPT_FIS) +#define PSW_1140 0170377 +#define PAR_1140 0007777 +#define PDR_1140 0077516 +#define MM0_1140 0160557 -#define SOP_1144 (BUS_U|OPT_EIS|OPT_FPP|OPT_MMU|OPT_UBM) -#define OPT_1144 (OPT_FPP|OPT_CIS) -#define PSW_1144 0170777 -#define PAR_1144 0177777 -#define PDR_1144 0177516 -#define MM0_1144 0160557 -#define MM3_1144 0000077 +#define SOP_1144 (BUS_U|OPT_EIS|OPT_FPP|OPT_MMU|OPT_UBM) +#define OPT_1144 (OPT_FPP|OPT_CIS) +#define PSW_1144 0170777 +#define PAR_1144 0177777 +#define PDR_1144 0177516 +#define MM0_1144 0160557 +#define MM3_1144 0000077 -#define SOP_1145 (BUS_U|OPT_EIS|OPT_FPP|OPT_MMU|OPT_RH11) -#define OPT_1145 (OPT_FPP) -#define PSW_1145 0174377 -#define PAR_1145 0007777 -#define PDR_1145 0077717 -#define MM0_1145 0171777 -#define MM3_1145 0000007 +#define SOP_1145 (BUS_U|OPT_EIS|OPT_FPP|OPT_MMU|OPT_RH11) +#define OPT_1145 (OPT_FPP) +#define PSW_1145 0174377 +#define PAR_1145 0007777 +#define PDR_1145 0077717 +#define MM0_1145 0171777 +#define MM3_1145 0000007 -#define SOP_1160 (BUS_U|OPT_EIS|OPT_FPP|OPT_MMU) -#define OPT_1160 0 -#define PSW_1160 0170377 -#define PAR_1160 0007777 -#define PDR_1160 0077516 -#define MM0_1160 0160557 +#define SOP_1160 (BUS_U|OPT_EIS|OPT_FPP|OPT_MMU) +#define OPT_1160 0 +#define PSW_1160 0170377 +#define PAR_1160 0007777 +#define PDR_1160 0077516 +#define MM0_1160 0160557 -#define SOP_1170 (BUS_U|OPT_EIS|OPT_FPP|OPT_MMU|OPT_UBM) -#define OPT_1170 (OPT_FPP|OPT_RH11) -#define PSW_1170 0174377 -#define PAR_1170 0177777 -#define PDR_1170 0077717 -#define MM0_1170 0171777 -#define MM3_1170 0000067 +#define SOP_1170 (BUS_U|OPT_EIS|OPT_FPP|OPT_MMU|OPT_UBM) +#define OPT_1170 (OPT_FPP|OPT_RH11) +#define PSW_1170 0174377 +#define PAR_1170 0177777 +#define PDR_1170 0077717 +#define MM0_1170 0171777 +#define MM3_1170 0000067 -#define SOP_1173 (BUS_Q|OPT_EIS|OPT_FPP|OPT_MMU) -#define OPT_1173 (OPT_CIS) -#define PSW_J 0174777 -#define PAR_J 0177777 -#define PDR_J 0177516 -#define MM0_J 0160177 -#define MM3_J 0000077 +#define SOP_1173 (BUS_Q|OPT_EIS|OPT_FPP|OPT_MMU) +#define OPT_1173 (OPT_CIS) +#define PSW_J 0174777 +#define PAR_J 0177777 +#define PDR_J 0177516 +#define MM0_J 0160177 +#define MM3_J 0000077 -#define SOP_1153 (BUS_Q|OPT_EIS|OPT_FPP|OPT_MMU) -#define OPT_1153 (OPT_CIS) +#define SOP_1153 (BUS_Q|OPT_EIS|OPT_FPP|OPT_MMU) +#define OPT_1153 (OPT_CIS) -#define SOP_1173B (BUS_Q|OPT_EIS|OPT_FPP|OPT_MMU) -#define OPT_1173B (OPT_CIS) +#define SOP_1173B (BUS_Q|OPT_EIS|OPT_FPP|OPT_MMU) +#define OPT_1173B (OPT_CIS) -#define SOP_1183 (BUS_Q|OPT_EIS|OPT_FPP|OPT_MMU) -#define OPT_1183 (OPT_CIS) +#define SOP_1183 (BUS_Q|OPT_EIS|OPT_FPP|OPT_MMU) +#define OPT_1183 (OPT_CIS) -#define SOP_1184 (BUS_U|OPT_EIS|OPT_FPP|OPT_MMU|OPT_UBM|OPT_RH11) -#define OPT_1184 (OPT_CIS) +#define SOP_1184 (BUS_U|OPT_EIS|OPT_FPP|OPT_MMU|OPT_UBM|OPT_RH11) +#define OPT_1184 (OPT_CIS) -#define SOP_1193 (BUS_Q|OPT_EIS|OPT_FPP|OPT_MMU) -#define OPT_1193 (OPT_CIS) +#define SOP_1193 (BUS_Q|OPT_EIS|OPT_FPP|OPT_MMU) +#define OPT_1193 (OPT_CIS) -#define SOP_1194 (BUS_U|OPT_EIS|OPT_FPP|OPT_MMU|OPT_UBM|OPT_RH11) -#define OPT_1194 (OPT_CIS) +#define SOP_1194 (BUS_U|OPT_EIS|OPT_FPP|OPT_MMU|OPT_UBM|OPT_RH11) +#define OPT_1194 (OPT_CIS) -#define MOD_MAX 20 +#define MOD_MAX 20 /* MFPT codes */ -#define MFPT_44 1 -#define MFPT_F 3 -#define MFPT_T 4 -#define MFPT_J 5 +#define MFPT_44 1 +#define MFPT_F 3 +#define MFPT_T 4 +#define MFPT_J 5 /* KDF11B specific register */ -#define PCRFB_RW 0037477 /* page ctrl reg */ +#define PCRFB_RW 0037477 /* page ctrl reg */ -#define CDRFB_RD 0000377 /* config reg */ -#define CDRFB_WR 0000017 +#define CDRFB_RD 0000377 /* config reg */ +#define CDRFB_WR 0000017 /* KT24 Unibus map specific registers */ -#define LMAL_RD 0177777 /* last mapped low */ +#define LMAL_RD 0177777 /* last mapped low */ -#define LMAH_RD 0000177 /* last mapped high */ -#define LMAH_WR 0000100 +#define LMAH_RD 0000177 /* last mapped high */ +#define LMAH_WR 0000100 /* 11/44 specific registers */ -#define CCR44_RD 0033315 /* cache control */ -#define CCR44_WR 0003315 +#define CCR44_RD 0033315 /* cache control */ +#define CCR44_WR 0003315 -#define CMR44_RD 0177437 /* cache maint */ -#define CMR44_WR 0000037 +#define CMR44_RD 0177437 /* cache maint */ +#define CMR44_WR 0000037 -#define CPUE44_BUSE 0004000 +#define CPUE44_BUSE 0004000 + +/* 11/60 specific registers */ + +#define WCS60_RD 0161776 /* WCS control */ +#define WCS60_WR 0061676 + +#define MEME60_RD 0100340 /* memory error */ + +#define CCR60_RD 0000315 /* cache control */ +#define CCR60_WR 0000115 + +#define MBRK60_WR 0007777 /* microbreak */ + +#define CPUE60_RD (CPUE_ODD|CPUE_TMO|CPUE_RED) /* J11 specific registers */ /* 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_KDJA (1 << MAINT_V_TYP) /* KDJ11A */ -#define MAINT_KDJB (2 << MAINT_V_TYP) /* KDJ11B */ -#define MAINT_KDJD (4 << MAINT_V_TYP) /* KDJ11D */ -#define MAINT_KDJE (5 << MAINT_V_TYP) /* KDJ11E */ -#define MAINT_V_HTRAP 3 /* trap 4 on HALT */ -#define MAINT_HTRAP (1 << MAINT_V_HTRAP) -#define MAINT_V_POM 1 /* power on option */ -#define MAINT_POODT (0 << MAINT_V_POM) /* power up ODT */ -#define MAINT_POROM (2 << MAINT_V_POM) /* power up ROM */ -#define MAINT_V_BPOK 0 /* power OK */ -#define MAINT_BPOK (1 << MAINT_V_BPOK) +#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_KDJA (1 << MAINT_V_TYP) /* KDJ11A */ +#define MAINT_KDJB (2 << MAINT_V_TYP) /* KDJ11B */ +#define MAINT_KDJD (4 << MAINT_V_TYP) /* KDJ11D */ +#define MAINT_KDJE (5 << MAINT_V_TYP) /* KDJ11E */ +#define MAINT_V_HTRAP 3 /* trap 4 on HALT */ +#define MAINT_HTRAP (1 << MAINT_V_HTRAP) +#define MAINT_V_POM 1 /* power on option */ +#define MAINT_POODT (0 << MAINT_V_POM) /* power up ODT */ +#define MAINT_POROM (2 << MAINT_V_POM) /* power up ROM */ +#define MAINT_V_BPOK 0 /* power OK */ +#define MAINT_BPOK (1 << MAINT_V_BPOK) /* KDJ11B control */ -#define CSRJB_RD 0177767 -#define CSRJB_WR 0037767 -#define CSRJ_LTCI 0020000 /* force LTC int */ -#define CSRJ_LTCD 0010000 /* disable LTC reg */ -#define CSRJ_V_LTCSEL 10 -#define CSRJ_M_LTCSEL 03 -#define CSRJ_LTCSEL(x) (((x) >> CSRJ_V_LTCSEL) & CSRJ_M_LTCSEL) -#define CSRJ_HBREAK 0001000 /* halt on break */ +#define CSRJB_RD 0177767 +#define CSRJB_WR 0037767 +#define CSRJ_LTCI 0020000 /* force LTC int */ +#define CSRJ_LTCD 0010000 /* disable LTC reg */ +#define CSRJ_V_LTCSEL 10 +#define CSRJ_M_LTCSEL 03 +#define CSRJ_LTCSEL(x) (((x) >> CSRJ_V_LTCSEL) & CSRJ_M_LTCSEL) +#define CSRJ_HBREAK 0001000 /* halt on break */ -#define PCRJB_RW 0077176 /* page ctrl reg */ +#define PCRJB_RW 0077176 /* page ctrl reg */ -#define CDRJB_RD 0000377 /* config register */ -#define CDRJB_WR 0000377 +#define CDRJB_RD 0000377 /* config register */ +#define CDRJB_WR 0000377 /* KDJ11D control */ -#define CSRJD_RD 0157777 /* native register */ -#define CSRJD_WR 0000377 -#define CSRJD_15M 0040000 /* 1.5M mem on board */ +#define CSRJD_RD 0157777 /* native register */ +#define CSRJD_WR 0000377 +#define CSRJD_15M 0040000 /* 1.5M mem on board */ /* KDJ11E control */ -#define CSRJE_RD 0137360 /* control reg */ -#define CSRJE_WR 0037370 +#define CSRJE_RD 0137360 /* control reg */ +#define CSRJE_WR 0037370 -#define PCRJE_RW 0177376 /* page ctrl reg */ +#define PCRJE_RW 0177376 /* page ctrl reg */ -#define CDRJE_RD 0000377 /* config register */ -#define CDRJE_WR 0000077 +#define CDRJE_RD 0000377 /* config register */ +#define CDRJE_WR 0000077 -#define ASRJE_RW 0030462 /* additional status */ -#define ASRJE_V_TOY 8 -#define ASRJE_TOY (1u << ASRJE_V_TOY) /* TOY serial bit */ -#define ASRJE_TOYBIT(x) (((x) >> ASRJE_V_TOY) & 1) +#define ASRJE_RW 0030462 /* additional status */ +#define ASRJE_V_TOY 8 +#define ASRJE_TOY (1u << ASRJE_V_TOY) /* TOY serial bit */ +#define ASRJE_TOYBIT(x) (((x) >> ASRJE_V_TOY) & 1) /* KDJ11E TOY clock */ -#define TOY_HSEC 0 -#define TOY_SEC 1 -#define TOY_MIN 2 -#define TOY_HR 3 -#define TOY_DOW 4 -#define TOY_DOM 5 -#define TOY_MON 6 -#define TOY_YR 7 -#define TOY_LNT 8 +#define TOY_HSEC 0 +#define TOY_SEC 1 +#define TOY_MIN 2 +#define TOY_HR 3 +#define TOY_DOW 4 +#define TOY_DOM 5 +#define TOY_MON 6 +#define TOY_YR 7 +#define TOY_LNT 8 /* KTJ11B Unibus map */ -#define DCRKTJ_RD 0100616 /* diag control */ -#define DCRKTJ_WR 0000416 +#define DCRKTJ_RD 0100616 /* diag control */ +#define DCRKTJ_WR 0000416 -#define DDRKTJ_RW 0177777 /* diag data */ +#define DDRKTJ_RW 0177777 /* diag data */ -#define MCRKTJ_RD 0000377 /* control register */ -#define MCRKTJ_WR 0000177 +#define MCRKTJ_RD 0000377 /* control register */ +#define MCRKTJ_WR 0000177 /* Data tables */ struct cpu_table { - char *name; /* model name */ - uint32 std; /* standard flags */ - uint32 opt; /* set/clear flags */ - uint32 maxm; /* max memory */ - uint32 psw; /* PSW mask */ - uint32 mfpt; /* MFPT code */ - uint32 par; /* PAR mask */ - uint32 pdr; /* PDR mask */ - uint32 mm0; /* MMR0 mask */ - uint32 mm3; /* MMR3 mask */ - }; + char *name; /* model name */ + uint32 std; /* standard flags */ + uint32 opt; /* set/clear flags */ + uint32 maxm; /* max memory */ + uint32 psw; /* PSW mask */ + uint32 mfpt; /* MFPT code */ + uint32 par; /* PAR mask */ + uint32 pdr; /* PDR mask */ + uint32 mm0; /* MMR0 mask */ + uint32 mm3; /* MMR3 mask */ + }; typedef struct cpu_table CPUTAB; struct conf_table { - uint32 cpum; - uint32 optm; - DIB *dib; - }; + uint32 cpum; + uint32 optm; + DIB *dib; + }; typedef struct conf_table CNFTAB; diff --git a/PDP11/pdp11_defs.h b/PDP11/pdp11_defs.h index 9dafa6ab..294b90fd 100644 --- a/PDP11/pdp11_defs.h +++ b/PDP11/pdp11_defs.h @@ -1,6 +1,6 @@ /* pdp11_defs.h: PDP-11 simulator definitions - Copyright (c) 1993-2004, Robert M Supnik + Copyright (c) 1993-2005, 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"), @@ -19,752 +19,741 @@ 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 + 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 - 30-Sep-04 RMS Added Massbus support - Removed Map_Addr prototype - Removed map argument from Unibus routines - Added framework for model selection - 28-May-04 RMS Added DHQ support - 25-Jan-04 RMS Removed local debug logging support - 22-Dec-03 RMS Added second DEUNA/DELUA support - 18-Oct-03 RMS Added DECtape off reel message - 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 + 30-Sep-04 RMS Added Massbus support + Removed Map_Addr prototype + Removed map argument from Unibus routines + Added framework for model selection + 28-May-04 RMS Added DHQ support + 25-Jan-04 RMS Removed local debug logging support + 22-Dec-03 RMS Added second DEUNA/DELUA support + 18-Oct-03 RMS Added DECtape off reel message + 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 +#define _PDP11_DEFS_H 0 #ifndef VM_PDP11 -#define VM_PDP11 0 +#define VM_PDP11 0 #endif -#include "sim_defs.h" /* simulator defns */ +#include "sim_defs.h" /* simulator defns */ #include /* Architectural constants */ -#define STKL_R 0340 /* stack limit */ -#define STKL_Y 0400 -#define VASIZE 0200000 /* 2**16 */ -#define VAMASK (VASIZE - 1) /* 2**16 - 1 */ -#define MEMSIZE64K 0200000 /* 2**16 */ -#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 IOPAGESIZE 000020000 /* 2**13 */ -#define IOPAGEMASK (IOPAGESIZE - 1) /* 2**13 - 1 */ -#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 +#define STKL_R 0340 /* stack limit */ +#define STKL_Y 0400 +#define VASIZE 0200000 /* 2**16 */ +#define VAMASK (VASIZE - 1) /* 2**16 - 1 */ +#define MEMSIZE64K 0200000 /* 2**16 */ +#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 IOPAGESIZE 000020000 /* 2**13 */ +#define IOPAGEMASK (IOPAGESIZE - 1) /* 2**13 - 1 */ +#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 /* CPU models */ -#define MOD_1103 0 -#define MOD_1104 1 -#define MOD_1105 2 -#define MOD_1120 3 -#define MOD_1123 4 -#define MOD_1123P 5 -#define MOD_1124 6 -#define MOD_1134 7 -#define MOD_1140 8 -#define MOD_1144 9 -#define MOD_1145 10 -#define MOD_1160 11 -#define MOD_1170 12 -#define MOD_1173 13 -#define MOD_1153 14 -#define MOD_1173B 15 -#define MOD_1183 16 -#define MOD_1184 17 -#define MOD_1193 18 -#define MOD_1194 19 -#define MOD_T 20 +#define MOD_1103 0 +#define MOD_1104 1 +#define MOD_1105 2 +#define MOD_1120 3 +#define MOD_1123 4 +#define MOD_1123P 5 +#define MOD_1124 6 +#define MOD_1134 7 +#define MOD_1140 8 +#define MOD_1144 9 +#define MOD_1145 10 +#define MOD_1160 11 +#define MOD_1170 12 +#define MOD_1173 13 +#define MOD_1153 14 +#define MOD_1173B 15 +#define MOD_1183 16 +#define MOD_1184 17 +#define MOD_1193 18 +#define MOD_1194 19 +#define MOD_T 20 -#define CPUT_03 (1u << MOD_1103) /* LSI-11 */ -#define CPUT_04 (1u << MOD_1104) /* 11/04 */ -#define CPUT_05 (1u << MOD_1105) /* 11/05 */ -#define CPUT_20 (1u << MOD_1120) /* 11/20 */ -#define CPUT_23 (1u << MOD_1123) /* 11/23 */ -#define CPUT_23P (1u << MOD_1123P) /* 11/23+ */ -#define CPUT_24 (1u << MOD_1124) /* 11/24 */ -#define CPUT_34 (1u << MOD_1134) /* 11/34 */ -#define CPUT_40 (1u << MOD_1140) /* 11/40 */ -#define CPUT_44 (1u << MOD_1144) /* 11/44 */ -#define CPUT_45 (1u << MOD_1145) /* 11/45 */ -#define CPUT_60 (1u << MOD_1160) /* 11/60 */ -#define CPUT_70 (1u << MOD_1170) /* 11/70 */ -#define CPUT_73 (1u << MOD_1173) /* 11/73 */ -#define CPUT_53 (1u << MOD_1153) /* 11/53 */ -#define CPUT_73B (1u << MOD_1173B) /* 11/73B */ -#define CPUT_83 (1u << MOD_1183) /* 11/83 */ -#define CPUT_84 (1u << MOD_1184) /* 11/84 */ -#define CPUT_93 (1u << MOD_1193) /* 11/93 */ -#define CPUT_94 (1u << MOD_1194) /* 11/94 */ -#define CPUT_T (1u << MOD_T) /* T-11 */ +#define CPUT_03 (1u << MOD_1103) /* LSI-11 */ +#define CPUT_04 (1u << MOD_1104) /* 11/04 */ +#define CPUT_05 (1u << MOD_1105) /* 11/05 */ +#define CPUT_20 (1u << MOD_1120) /* 11/20 */ +#define CPUT_23 (1u << MOD_1123) /* 11/23 */ +#define CPUT_23P (1u << MOD_1123P) /* 11/23+ */ +#define CPUT_24 (1u << MOD_1124) /* 11/24 */ +#define CPUT_34 (1u << MOD_1134) /* 11/34 */ +#define CPUT_40 (1u << MOD_1140) /* 11/40 */ +#define CPUT_44 (1u << MOD_1144) /* 11/44 */ +#define CPUT_45 (1u << MOD_1145) /* 11/45 */ +#define CPUT_60 (1u << MOD_1160) /* 11/60 */ +#define CPUT_70 (1u << MOD_1170) /* 11/70 */ +#define CPUT_73 (1u << MOD_1173) /* 11/73 */ +#define CPUT_53 (1u << MOD_1153) /* 11/53 */ +#define CPUT_73B (1u << MOD_1173B) /* 11/73B */ +#define CPUT_83 (1u << MOD_1183) /* 11/83 */ +#define CPUT_84 (1u << MOD_1184) /* 11/84 */ +#define CPUT_93 (1u << MOD_1193) /* 11/93 */ +#define CPUT_94 (1u << MOD_1194) /* 11/94 */ +#define CPUT_T (1u << MOD_T) /* T-11 */ -#define CPUT_F (CPUT_23|CPUT_23P|CPUT_24) /* all F11's */ -#define CPUT_J (CPUT_53|CPUT_73|CPUT_73B| \ - CPUT_83|CPUT_84|CPUT_93|CPUT_94) -#define CPUT_JB (CPUT_73B|CPUT_83|CPUT_84) /* KDJ11B */ -#define CPUT_JE (CPUT_93|CPUT_94) /* KDJ11E */ -#define CPUT_JU (CPUT_84|CPUT_94) /* KTJ11B UBA */ -#define CPUT_ALL 0xFFFFFFFF +#define CPUT_F (CPUT_23|CPUT_23P|CPUT_24) /* all F11's */ +#define CPUT_J (CPUT_53|CPUT_73|CPUT_73B| \ + CPUT_83|CPUT_84|CPUT_93|CPUT_94) +#define CPUT_JB (CPUT_73B|CPUT_83|CPUT_84) /* KDJ11B */ +#define CPUT_JE (CPUT_93|CPUT_94) /* KDJ11E */ +#define CPUT_JU (CPUT_84|CPUT_94) /* KTJ11B UBA */ +#define CPUT_ALL 0xFFFFFFFF /* CPU options */ -#define BUS_U (1u << 0) /* Unibus */ -#define BUS_Q (0) /* Qbus */ -#define OPT_EIS (1u << 1) /* EIS */ -#define OPT_FIS (1u << 2) /* FIS */ -#define OPT_FPP (1u << 3) /* FPP */ -#define OPT_CIS (1u << 4) /* CIS */ -#define OPT_MMU (1u << 5) /* MMU */ -#define OPT_RH11 (1u << 6) /* RH11 */ -#define OPT_PAR (1u << 7) /* parity */ -#define OPT_UBM (1u << 8) /* UBM */ +#define BUS_U (1u << 0) /* Unibus */ +#define BUS_Q (0) /* Qbus */ +#define OPT_EIS (1u << 1) /* EIS */ +#define OPT_FIS (1u << 2) /* FIS */ +#define OPT_FPP (1u << 3) /* FPP */ +#define OPT_CIS (1u << 4) /* CIS */ +#define OPT_MMU (1u << 5) /* MMU */ +#define OPT_RH11 (1u << 6) /* RH11 */ +#define OPT_PAR (1u << 7) /* parity */ +#define OPT_UBM (1u << 8) /* UBM */ -#define CPUT(x) ((cpu_type & (x)) != 0) -#define CPUO(x) ((cpu_opt & (x)) != 0) -#define UNIBUS (cpu_opt & BUS_U) +#define CPUT(x) ((cpu_type & (x)) != 0) +#define CPUO(x) ((cpu_opt & (x)) != 0) +#define UNIBUS (cpu_opt & BUS_U) /* Feature sets - SDSD source addr, source fetch, dest addr, dest fetch - SR switch register - DR display register - RTT RTT instruction - SXS SXT, XOR, SOB instructions - MARK MARK instruction - SPL SPL instruction - MXPY MTPI, MTPD, MFPI, MFPD instructions - MXPS MTPS, MFPS instructions - MFPT MFPT instruction - CSM CSM instruction - TSWLK TSTSET, WRLCK instructions - PSW PSW register - EXPT explicit PSW writes can alter T-bit - IOSR general registers readable from programs in IO space - 2REG dual register set - MMR3 MMR3 register - MMTR mem mgt traps - STKLR STKLIM register - STKLF fixed stack limit - SID supervisor mode, I/D spaces - ODD odd address trap - HALT4 halt in kernel mode traps to 4 - JREG4 JMP/JSR R traps to 4 - STKA stop on stack abort - LTCR LTC CSR - LTCM LTC CSR<7> + SDSD source addr, source fetch, dest addr, dest fetch + SR switch register + DR display register + RTT RTT instruction + SXS SXT, XOR, SOB instructions + MARK MARK instruction + SPL SPL instruction + MXPY MTPI, MTPD, MFPI, MFPD instructions + MXPS MTPS, MFPS instructions + MFPT MFPT instruction + CSM CSM instruction + TSWLK TSTSET, WRLCK instructions + PSW PSW register + EXPT explicit PSW writes can alter T-bit + IOSR general registers readable from programs in IO space + 2REG dual register set + MMR3 MMR3 register + MMTR mem mgt traps + STKLR STKLIM register + STKLF fixed stack limit + SID supervisor mode, I/D spaces + ODD odd address trap + HALT4 halt in kernel mode traps to 4 + JREG4 JMP/JSR R traps to 4 + STKA stop on stack abort + LTCR LTC CSR + LTCM LTC CSR<7> */ -#define IS_SDSD (CPUT_20|CPUT_F|CPUT_40|CPUT_60|CPUT_J|CPUT_T) -#define HAS_SR (CPUT_04|CPUT_05|CPUT_20|CPUT_34|CPUT_40| \ - CPUT_44|CPUT_45|CPUT_60|CPUT_70) -#define HAS_DR (CPUT_04|CPUT_05|CPUT_20|CPUT_24|CPUT_34| \ - CPUT_40|CPUT_45|CPUT_60|CPUT_70) -#define HAS_RTT (CPUT_03|CPUT_04|CPUT_F|CPUT_34|CPUT_40| \ - CPUT_44|CPUT_45|CPUT_60|CPUT_70|CPUT_J|CPUT_T) -#define HAS_SXS (CPUT_03|CPUT_F|CPUT_34|CPUT_40|CPUT_44| \ - CPUT_45|CPUT_60|CPUT_70|CPUT_J|CPUT_T) -#define HAS_MARK (CPUT_03|CPUT_F|CPUT_34|CPUT_40|CPUT_44| \ - CPUT_45|CPUT_60|CPUT_70|CPUT_J) -#define HAS_SPL (CPUT_44|CPUT_45|CPUT_70|CPUT_J) -#define HAS_MXPY (CPUT_F|CPUT_34|CPUT_40|CPUT_44|CPUT_45| \ - CPUT_60|CPUT_70|CPUT_J) -#define HAS_MXPS (CPUT_03|CPUT_F|CPUT_34|CPUT_J|CPUT_T) -#define HAS_MFPT (CPUT_F|CPUT_44|CPUT_J|CPUT_T) -#define HAS_CSM (CPUT_44|CPUT_J) -#define HAS_TSWLK (CPUT_J) -#define HAS_PSW (CPUT_04|CPUT_05|CPUT_20|CPUT_F|CPUT_34|CPUT_40| \ - CPUT_44|CPUT_45|CPUT_60|CPUT_70|CPUT_J) -#define HAS_EXPT (CPUT_04|CPUT_05|CPUT_20) -#define HAS_IOSR (CPUT_04|CPUT_05) -#define HAS_2REG (CPUT_45|CPUT_70|CPUT_J) -#define HAS_MMR3 (CPUT_F|CPUT_44|CPUT_45|CPUT_70|CPUT_J) -#define HAS_MMTR (CPUT_45|CPUT_70) -#define HAS_STKLR (CPUT_45|CPUT_60|CPUT_70) -#define HAS_STKLF (CPUT_04|CPUT_05|CPUT_20|CPUT_F|CPUT_34| \ - CPUT_40|CPUT_44|CPUT_J) -#define HAS_SID (CPUT_44|CPUT_45|CPUT_70|CPUT_J) -#define HAS_ODD (CPUT_04|CPUT_05|CPUT_20|CPUT_34|CPUT_40| \ - CPUT_44|CPUT_45|CPUT_60|CPUT_70|CPUT_J) -#define HAS_HALT4 (CPUT_44|CPUT_45|CPUT_70|CPUT_J) -#define HAS_JREG4 (CPUT_03|CPUT_04|CPUT_05|CPUT_20|CPUT_F| \ - CPUT_34|CPUT_40|CPUT_60|CPUT_T) -#define STOP_STKA (CPUT_03|CPUT_04|CPUT_05|CPUT_20|CPUT_34|CPUT_44) -#define HAS_LTCR (CPUT_04|CPUT_05|CPUT_20|CPUT_23P|CPUT_24| \ - CPUT_34|CPUT_40|CPUT_44|CPUT_45|CPUT_60| \ - CPUT_70|CPUT_J) -#define HAS_LTCM (CPUT_04|CPUT_05|CPUT_20|CPUT_24|CPUT_34| \ - CPUT_40|CPUT_44|CPUT_45|CPUT_60|CPUT_70|CPUT_J) +#define IS_SDSD (CPUT_20|CPUT_F|CPUT_40|CPUT_60|CPUT_J|CPUT_T) +#define HAS_SR (CPUT_04|CPUT_05|CPUT_20|CPUT_34|CPUT_40| \ + CPUT_44|CPUT_45|CPUT_60|CPUT_70) +#define HAS_DR (CPUT_04|CPUT_05|CPUT_20|CPUT_24|CPUT_34| \ + CPUT_40|CPUT_45|CPUT_60|CPUT_70) +#define HAS_RTT (CPUT_03|CPUT_04|CPUT_F|CPUT_34|CPUT_40| \ + CPUT_44|CPUT_45|CPUT_60|CPUT_70|CPUT_J|CPUT_T) +#define HAS_SXS (CPUT_03|CPUT_F|CPUT_34|CPUT_40|CPUT_44| \ + CPUT_45|CPUT_60|CPUT_70|CPUT_J|CPUT_T) +#define HAS_MARK (CPUT_03|CPUT_F|CPUT_34|CPUT_40|CPUT_44| \ + CPUT_45|CPUT_60|CPUT_70|CPUT_J) +#define HAS_SPL (CPUT_44|CPUT_45|CPUT_70|CPUT_J) +#define HAS_MXPY (CPUT_F|CPUT_34|CPUT_40|CPUT_44|CPUT_45| \ + CPUT_60|CPUT_70|CPUT_J) +#define HAS_MXPS (CPUT_03|CPUT_F|CPUT_34|CPUT_J|CPUT_T) +#define HAS_MFPT (CPUT_F|CPUT_44|CPUT_J|CPUT_T) +#define HAS_CSM (CPUT_44|CPUT_J) +#define HAS_TSWLK (CPUT_J) +#define HAS_PSW (CPUT_04|CPUT_05|CPUT_20|CPUT_F|CPUT_34|CPUT_40| \ + CPUT_44|CPUT_45|CPUT_60|CPUT_70|CPUT_J) +#define HAS_EXPT (CPUT_04|CPUT_05|CPUT_20) +#define HAS_IOSR (CPUT_04|CPUT_05) +#define HAS_2REG (CPUT_45|CPUT_70|CPUT_J) +#define HAS_MMR3 (CPUT_F|CPUT_44|CPUT_45|CPUT_70|CPUT_J) +#define HAS_MMTR (CPUT_45|CPUT_70) +#define HAS_STKLR (CPUT_45|CPUT_60|CPUT_70) +#define HAS_STKLF (CPUT_04|CPUT_05|CPUT_20|CPUT_F|CPUT_34| \ + CPUT_40|CPUT_44|CPUT_J) +#define HAS_SID (CPUT_44|CPUT_45|CPUT_70|CPUT_J) +#define HAS_ODD (CPUT_04|CPUT_05|CPUT_20|CPUT_34|CPUT_40| \ + CPUT_44|CPUT_45|CPUT_60|CPUT_70|CPUT_J) +#define HAS_HALT4 (CPUT_44|CPUT_45|CPUT_70|CPUT_J) +#define HAS_JREG4 (CPUT_03|CPUT_04|CPUT_05|CPUT_20|CPUT_F| \ + CPUT_34|CPUT_40|CPUT_60|CPUT_T) +#define STOP_STKA (CPUT_03|CPUT_04|CPUT_05|CPUT_20|CPUT_34|CPUT_44) +#define HAS_LTCR (CPUT_04|CPUT_05|CPUT_20|CPUT_23P|CPUT_24| \ + CPUT_34|CPUT_40|CPUT_44|CPUT_45|CPUT_60| \ + CPUT_70|CPUT_J) +#define HAS_LTCM (CPUT_04|CPUT_05|CPUT_20|CPUT_24|CPUT_34| \ + CPUT_40|CPUT_44|CPUT_45|CPUT_60|CPUT_70|CPUT_J) /* Protection modes */ -#define MD_KER 0 -#define MD_SUP 1 -#define MD_UND 2 -#define MD_USR 3 +#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 +#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_FPD 8 /* first part done */ -#define PSW_V_RS 11 /* register set */ -#define PSW_V_PM 12 /* previous mode */ -#define PSW_V_CM 14 /* current mode */ -#define PSW_CC 017 -#define PSW_TBIT (1 << PSW_V_TBIT) -#define PSW_PM (3 << PSW_V_PM) +#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_FPD 8 /* first part done */ +#define PSW_V_RS 11 /* register set */ +#define PSW_V_PM 12 /* previous mode */ +#define PSW_V_CM 14 /* current mode */ +#define PSW_CC 017 +#define PSW_TBIT (1 << PSW_V_TBIT) +#define PSW_PM (3 << PSW_V_PM) /* 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 */ +#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 */ +#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 */ /* STKLIM */ -#define STKLIM_RW 0177400 +#define STKLIM_RW 0177400 /* 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_IC 0000200 /* instr complete */ -#define MMR0_MAINT 0000400 /* maintenance */ -#define MMR0_TENB 0001000 /* trap enable */ -#define MMR0_TRAP 0010000 /* mem mgt trap */ -#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_WR 0171401 /* writeable bits */ +#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_IC 0000200 /* instr complete */ +#define MMR0_MAINT 0000400 /* maintenance */ +#define MMR0_TENB 0001000 /* trap enable */ +#define MMR0_TRAP 0010000 /* mem mgt trap */ +#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_WR 0171401 /* writeable 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_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 */ /* PAR */ -#define PAR_18B 0007777 /* 18b addressing */ -#define PAR_22B 0177777 /* 22b addressing */ +#define PAR_18B 0007777 /* 18b addressing */ +#define PAR_22B 0177777 /* 22b addressing */ /* PDR */ -#define PDR_ACF 0000007 /* access control */ -#define PDR_ACS 0000006 /* 2b access control */ -#define PDR_ED 0000010 /* expansion dir */ -#define PDR_W 0000100 /* written flag */ -#define PDR_A 0000200 /* access flag */ -#define PDR_PLF 0077400 /* page lnt field */ -#define PDR_NOC 0100000 /* don't cache */ +#define PDR_ACF 0000007 /* access control */ +#define PDR_ACS 0000006 /* 2b access control */ +#define PDR_ED 0000010 /* expansion dir */ +#define PDR_W 0000100 /* written flag */ +#define PDR_A 0000200 /* access flag */ +#define PDR_PLF 0077400 /* page lnt field */ +#define PDR_NOC 0100000 /* don't cache */ -#define PDR_PRD 0000003 /* page readable if 2 */ +#define PDR_PRD 0000003 /* page readable if 2 */ /* 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 */ +#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_PAGSIZE (UBM_M_OFF + 1) /* page size */ -#define UBM_GETPN(x) (((x) >> UBM_V_PN) & UBM_M_PN) -#define UBM_GETOFF(x) ((x) & UBM_M_OFF) +#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_PAGSIZE (UBM_M_OFF + 1) /* page size */ +#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 */ +#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 */ /* Floating point accumulators */ -struct fpac { - uint32 l; /* low 32b */ - uint32 h; /* high 32b */ -}; -typedef struct fpac fpac_t; +typedef struct { + uint32 l; /* low 32b */ + uint32 h; /* high 32b */ + } 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) +#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 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 +#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 STOP_DTOFF (TRAP_V_MAX + 8) /* DECtape off reel */ -#define IORETURN(f,v) ((f)? (v): SCPE_OK) /* cond error return */ +#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 STOP_DTOFF (TRAP_V_MAX + 8) /* DECtape off reel */ +#define IORETURN(f,v) ((f)? (v): SCPE_OK) /* cond error return */ /* Timers */ -#define TMR_CLK 0 /* line clock */ -#define TMR_PCLK 1 /* KW11P */ +#define TMR_CLK 0 /* line clock */ +#define TMR_PCLK 1 /* KW11P */ /* IO parameters */ -#define DZ_MUXES 4 /* max # of DZ muxes */ -#define DZ_LINES 8 /* lines per DZ mux */ -#define VH_MUXES 4 /* max # of VH muxes */ -#define MT_MAXFR (1 << 16) /* magtape max rec */ -#define AUTO_LNT 34 /* autoconfig ranks */ -#define DIB_MAX 100 /* max DIBs */ +#define DZ_MUXES 4 /* max # of DZ muxes */ +#define DZ_LINES 8 /* lines per DZ mux */ +#define VH_MUXES 4 /* max # of VH muxes */ +#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_Q18 (DEV_V_UF + 2) /* Qbus with <= 256KB */ -#define DEV_V_FLTA (DEV_V_UF + 3) /* flt addr */ -#define DEV_V_MBUS (DEV_V_UF + 4) /* Massbus */ -#define DEV_V_FFUF (DEV_V_UF + 5) /* first free flag */ -#define DEV_UBUS (1u << DEV_V_UBUS) -#define DEV_QBUS (1u << DEV_V_QBUS) -#define DEV_Q18 (1u << DEV_V_Q18) -#define DEV_FLTA (1u << DEV_V_FLTA) -#define DEV_MBUS (1u << DEV_V_MBUS) +#define DEV_V_UBUS (DEV_V_UF + 0) /* Unibus */ +#define DEV_V_QBUS (DEV_V_UF + 1) /* Qbus */ +#define DEV_V_Q18 (DEV_V_UF + 2) /* Qbus with <= 256KB */ +#define DEV_V_FLTA (DEV_V_UF + 3) /* flt addr */ +#define DEV_V_MBUS (DEV_V_UF + 4) /* Massbus */ +#define DEV_V_FFUF (DEV_V_UF + 5) /* first free flag */ +#define DEV_UBUS (1u << DEV_V_UBUS) +#define DEV_QBUS (1u << DEV_V_QBUS) +#define DEV_Q18 (1u << DEV_V_Q18) +#define DEV_FLTA (1u << DEV_V_FLTA) +#define DEV_MBUS (1u << DEV_V_MBUS) -#define DEV_RDX 8 /* default device radix */ +#define DEV_RDX 8 /* default device radix */ /* Device information block */ -#define VEC_DEVMAX 4 /* max device vec */ +#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 */ -}; + 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 - XUB, RQB,RQC,RQD float based on number of DZ's */ -#define IOBA_DZ (IOPAGEBASE + 000100) /* DZ11 */ -#define IOLN_DZ 010 -#define IOBA_XUB (IOPAGEBASE + 000330 + (020 * (DZ_MUXES / 2))) -#define IOLN_XUB 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_VH (IOPAGEBASE + 000440) /* DHQ11 */ -#define IOLN_VH 020 -#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_SUP (IOPAGEBASE + 012200) /* supervisor APR's */ -#define IOLN_SUP 0100 -#define IOBA_KIPDR (IOPAGEBASE + 012300) /* kernel APR's */ -#define IOLN_KIPDR 020 -#define IOBA_KDPDR (IOPAGEBASE + 012320) -#define IOLN_KDPDR 020 -#define IOBA_KIPAR (IOPAGEBASE + 012340) -#define IOLN_KIPAR 020 -#define IOBA_KDPAR (IOPAGEBASE + 012360) -#define IOLN_KDPAR 020 -#define IOBA_TU (IOPAGEBASE + 012440) /* TU */ -#define IOLN_TU 040 -#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_CTL (IOPAGEBASE + 017520) /* board ctrl */ -#define IOLN_CTL 010 -#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_SR (IOPAGEBASE + 017570) /* SR */ -#define IOLN_SR 002 -#define IOBA_MMR012 (IOPAGEBASE + 017572) /* MMR0-2 */ -#define IOLN_MMR012 006 -#define IOBA_UIPDR (IOPAGEBASE + 017600) /* user APR's */ -#define IOLN_UIPDR 020 -#define IOBA_UDPDR (IOPAGEBASE + 017620) -#define IOLN_UDPDR 020 -#define IOBA_UIPAR (IOPAGEBASE + 017640) -#define IOLN_UIPAR 020 -#define IOBA_UDPAR (IOPAGEBASE + 017660) -#define IOLN_UDPAR 020 -#define IOBA_GPR (IOPAGEBASE + 017700) /* GPR's */ -#define IOLN_GPR 010 -#define IOBA_UCTL (IOPAGEBASE + 017730) /* UBA ctrl */ -#define IOLN_UCTL 010 -#define IOBA_CPU (IOPAGEBASE + 017740) /* CPU reg */ -#define IOLN_CPU 036 -#define IOBA_PSW (IOPAGEBASE + 017776) /* PSW */ -#define IOLN_PSW 002 +#define IOBA_DZ (IOPAGEBASE + 000100) /* DZ11 */ +#define IOLN_DZ 010 +#define IOBA_XUB (IOPAGEBASE + 000330 + (020 * (DZ_MUXES / 2))) +#define IOLN_XUB 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_VH (IOPAGEBASE + 000440) /* DHQ11 */ +#define IOLN_VH 020 +#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_SUP (IOPAGEBASE + 012200) /* supervisor APR's */ +#define IOLN_SUP 0100 +#define IOBA_KIPDR (IOPAGEBASE + 012300) /* kernel APR's */ +#define IOLN_KIPDR 020 +#define IOBA_KDPDR (IOPAGEBASE + 012320) +#define IOLN_KDPDR 020 +#define IOBA_KIPAR (IOPAGEBASE + 012340) +#define IOLN_KIPAR 020 +#define IOBA_KDPAR (IOPAGEBASE + 012360) +#define IOLN_KDPAR 020 +#define IOBA_TU (IOPAGEBASE + 012440) /* TU */ +#define IOLN_TU 040 +#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_CTL (IOPAGEBASE + 017520) /* board ctrl */ +#define IOLN_CTL 010 +#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_SR (IOPAGEBASE + 017570) /* SR */ +#define IOLN_SR 002 +#define IOBA_MMR012 (IOPAGEBASE + 017572) /* MMR0-2 */ +#define IOLN_MMR012 006 +#define IOBA_UIPDR (IOPAGEBASE + 017600) /* user APR's */ +#define IOLN_UIPDR 020 +#define IOBA_UDPDR (IOPAGEBASE + 017620) +#define IOLN_UDPDR 020 +#define IOBA_UIPAR (IOPAGEBASE + 017640) +#define IOLN_UIPAR 020 +#define IOBA_UDPAR (IOPAGEBASE + 017660) +#define IOLN_UDPAR 020 +#define IOBA_GPR (IOPAGEBASE + 017700) /* GPR's */ +#define IOLN_GPR 010 +#define IOBA_UCTL (IOPAGEBASE + 017730) /* UBA ctrl */ +#define IOLN_UCTL 010 +#define IOBA_CPU (IOPAGEBASE + 017740) /* CPU reg */ +#define IOLN_CPU 036 +#define IOBA_PSW (IOPAGEBASE + 017776) /* PSW */ +#define IOLN_PSW 002 /* Interrupt assignments; within each level, priority is right to left */ -#define IPL_HLVL 8 /* # int levels */ +#define IPL_HLVL 8 /* # int levels */ -#define INT_V_PIR7 0 /* BR7 */ +#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_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_TU 14 -#define INT_V_PIR5 15 +#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_TU 14 +#define INT_V_PIR5 15 -#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_VHRX 5 -#define INT_V_VHTX 6 -#define INT_V_PIR4 7 +#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_VHRX 5 +#define INT_V_VHTX 6 +#define INT_V_PIR4 7 -#define INT_V_PIR3 0 /* BR3 */ -#define INT_V_PIR2 0 /* BR2 */ -#define INT_V_PIR1 0 /* BR1 */ +#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_TU (1u << INT_V_TU) -#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_VHRX (1u << INT_V_VHRX) -#define INT_VHTX (1u << INT_V_VHTX) -#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 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_TU (1u << INT_V_TU) +#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_VHRX (1u << INT_V_VHRX) +#define INT_VHTX (1u << INT_V_VHTX) +#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_TU 5 -#define IPL_PTR 4 -#define IPL_PTP 4 -#define IPL_TTI 4 -#define IPL_TTO 4 -#define IPL_LPT 4 -#define IPL_VHRX 4 -#define IPL_VHTX 4 +#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_TU 5 +#define IPL_PTR 4 +#define IPL_PTP 4 +#define IPL_TTI 4 +#define IPL_TTO 4 +#define IPL_LPT 4 +#define IPL_VHRX 4 +#define IPL_VHTX 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 +#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_TU 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 -#define VEC_VHRX 0310 -#define VEC_VHTX 0314 - -/* 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 -#define RANK_VH 32 +#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_TU 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 +#define VEC_VHRX 0310 +#define VEC_VHTX 0314 /* 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 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) /* Massbus definitions */ -#define MBA_NUM 2 /* number of MBA's */ -#define MBA_RP 0 /* MBA for RP */ -#define MBA_TU 1 /* MBA for TU */ -#define MBA_RMASK 037 /* max 32 reg */ -#define MBE_NXD 1 /* nx drive */ -#define MBE_NXR 2 /* nx reg */ -#define MBE_GOE 3 /* err on GO */ +#define MBA_NUM 2 /* number of MBA's */ +#define MBA_RP 0 /* MBA for RP */ +#define MBA_TU 1 /* MBA for TU */ +#define MBA_RMASK 037 /* max 32 reg */ +#define MBE_NXD 1 /* nx drive */ +#define MBE_NXR 2 /* nx reg */ +#define MBE_GOE 3 /* err on GO */ /* 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 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] @@ -780,7 +769,7 @@ 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); +t_stat auto_config (char *name, int32 nctrl); t_stat build_ubus_tab (DEVICE *dptr, DIB *dibp); int32 mba_rdbufW (uint32 mbus, int32 bc, uint16 *buf); diff --git a/PDP11/pdp11_doc.txt b/PDP11/pdp11_doc.txt index f1e90798..1fc8dae5 100644 --- a/PDP11/pdp11_doc.txt +++ b/PDP11/pdp11_doc.txt @@ -1,7 +1,7 @@ To: Users From: Bob Supnik Subj: PDP-11 Simulator Usage -Date: 20-Jan-2005 +Date: 01-Jul-2005 COPYRIGHT NOTICE @@ -27,8 +27,8 @@ The following copyright notice applies to both the SIMH source and binary: 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 + 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. @@ -104,7 +104,7 @@ PTR,PTP PC11 paper tape reader/punch TTI,TTO DL11 console terminal LPT LP11 line printer CLK line frequency clock -PCLK KW11P programmable clock +PCLK KW11-P programmable clock DZ DZ11 8-line terminal multiplexor (up to 4) VH DHU11/DHQ11 8-line terminal multiplexor (up to 4) RK RK11/RK05 cartridge disk controller with eight drives @@ -228,14 +228,14 @@ type bus memory MMU? Umap? EIS? FIS? FPP? CIS? If a capability is standard, it cannot be disabled; if a capability is not included, it cannot be enabled. -The CPU implements a show command to display the I/O address assignments: +The CPU implements a SHOW command to display the I/O address assignments: SHOW CPU IOSPACE show I/O space address assignments 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, +is being increased to more than 256KB, or the bus structure is being changed, the simulator asks whether it should disable peripherals that can't run in the current bus structure. @@ -378,7 +378,7 @@ disabled in a Qbus configuration with more than 256KB memory. 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: +presence of other devices in the configuration: DZ11 all instances have floating addresses DHU11/DHQ11 all instances have floating addresses @@ -1355,7 +1355,7 @@ 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 SET DZ DISCONNECT=linenumber command disconnects the specified line. The DZ11 implements these registers: @@ -1439,7 +1439,7 @@ a SET VH DISCONNECT command, or a DETACH VH command. The SHOW VH CONNECTIONS command displays the current connections to the VH. The SHOW VH STATISTICS command displays statistics for active connections. -The SET VH DISCONNECT=linenumber disconnects the specified line. +The SET VH DISCONNECT=linenumber command disconnects the specified line. The DHQ11 implements these registers, though not all can be examined from SCP: @@ -1537,7 +1537,7 @@ XQ and XQB have the following registers: VAR 16 vector address register INT 1 interrupt request flag -One final note: because of it's asynchronous nature, the XQ controller is +One final note: because of its 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!" :-) diff --git a/PDP11/pdp11_dz.c b/PDP11/pdp11_dz.c index eb9c8e83..865e4fca 100644 --- a/PDP11/pdp11_dz.c +++ b/PDP11/pdp11_dz.c @@ -1,6 +1,6 @@ /* pdp11_dz.c: DZ11 terminal multiplexor simulator - Copyright (c) 2001-2004, Robert M Supnik + Copyright (c) 2001-2005, 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"), @@ -19,145 +19,144 @@ 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 + 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 + dz DZ11 terminal multiplexor - 4-Apr-04 RMS Added per-line logging - 05-Jan-04 RMS Revised for tmxr library changes - 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 + 07-Jul-05 RMS Removed extraneous externs + 15-Jun-05 RMS Revised for new autoconfigure interface + 04-Apr-04 RMS Added per-line logging + 05-Jan-04 RMS Revised for tmxr library changes + 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 */ +#if defined (VM_PDP10) /* PDP10 version */ #include "pdp10_defs.h" -#define RANK_DZ 0 /* no autoconfig */ -#define DZ_8B_DFLT 0 +#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 */ +#elif defined (VM_VAX) /* VAX version */ #include "vax_defs.h" -#define DZ_8B_DFLT UNIT_8B +#define DZ_8B_DFLT UNIT_8B extern int32 int_req[IPL_HLVL]; -extern int32 int_vec[IPL_HLVL][32]; -#else /* PDP-11 version */ +#else /* PDP-11 version */ #include "pdp11_defs.h" -#define DZ_8B_DFLT UNIT_8B +#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 +#define DZ_MUXES 1 #endif #if !defined (DZ_LINES) -#define DZ_LINES 8 +#define DZ_LINES 8 #endif -#define UNIT_V_8B (UNIT_V_UF + 0) /* 8b output */ -#define UNIT_8B (1 << UNIT_V_8B) +#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 */ +#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_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) +#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 +#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) +#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 */ +#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 */ +#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 */ - +#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 */ +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, dz_ldsc }; /* mux descriptor */ +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, dz_ldsc }; /* mux descriptor */ DEVICE dz_dev; t_stat dz_rd (int32 *data, int32 PA, int32 access); @@ -183,178 +182,199 @@ t_stat dz_setnl (UNIT *uptr, int32 val, char *cptr, void *desc); t_stat dz_set_log (UNIT *uptr, int32 val, char *cptr, void *desc); t_stat dz_set_nolog (UNIT *uptr, int32 val, char *cptr, void *desc); t_stat dz_show_log (FILE *st, UNIT *uptr, int32 val, void *desc); - + /* DZ data structures - dz_dev DZ device descriptor - dz_unit DZ unit list - dz_reg DZ register list + 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 } }; +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 } }; + { 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 }, + { 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 }, + { 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 }, - { MTAB_XTD | MTAB_VDV, 0, NULL, "LOG", - &dz_set_log, NULL, &dz_desc }, - { MTAB_XTD | MTAB_VDV, 0, NULL, "NOLOG", - &dz_set_nolog, NULL, &dz_desc }, - { MTAB_XTD | MTAB_VDV | MTAB_NMO, 0, "LOG", NULL, - NULL, &dz_show_log, &dz_desc }, - { 0 } }; + { MTAB_XTD | MTAB_VDV | MTAB_VAL, 0, "lines", "LINES", + &dz_setnl, NULL, &dz_nlreg }, + { MTAB_XTD | MTAB_VDV, 0, NULL, "LOG", + &dz_set_log, NULL, &dz_desc }, + { MTAB_XTD | MTAB_VDV, 0, NULL, "NOLOG", + &dz_set_nolog, NULL, &dz_desc }, + { MTAB_XTD | MTAB_VDV | MTAB_NMO, 0, "LOG", NULL, + NULL, &dz_show_log, &dz_desc }, + { 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 }; - + "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 */ +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; + } -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 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_linemsg (lp, "\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; } +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_linemsg (lp, "\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 @@ -370,20 +390,22 @@ 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 */ +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; } @@ -393,12 +415,12 @@ 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 */ +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; } @@ -409,28 +431,30 @@ 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 */ + 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 */ +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; } @@ -441,38 +465,40 @@ 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; } } +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 */ + 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 */ +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 */ +dz_rxi = dz_rxi | (1 << dz); /* set mux rcv int */ +SET_INT (DZRX); /* set master intr */ return; } @@ -480,25 +506,27 @@ 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 */ +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 */ +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 */ +dz_txi = dz_txi | (1 << dz); /* set mux xmt int */ +SET_INT (DZTX); /* set master intr */ return; } @@ -506,32 +534,35 @@ 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 */ +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_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_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 */ +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; } @@ -539,13 +570,13 @@ t_stat dz_reset (DEVICE *dptr) { int32 i, ndev; -for (i = 0; i < DZ_MUXES; i++) dz_clear (i, TRUE); /* init muxes */ -dz_rxi = dz_txi = 0; /* clr master int */ +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 */ +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 */ +return auto_config (dptr->name, ndev); /* auto config */ } /* Attach */ @@ -555,19 +586,19 @@ 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"); - } - } +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; } @@ -577,15 +608,16 @@ 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; } +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; @@ -597,11 +629,13 @@ 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); } } +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; } @@ -620,18 +654,20 @@ 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; + return SCPE_OK; for (i = newln; i < dz_desc.lines; i++) { - if (dz_ldsc[i].conn) { - tmxr_linemsg (&dz_ldsc[i], "\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 */ + if (dz_ldsc[i].conn) { + tmxr_linemsg (&dz_ldsc[i], "\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_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 */ +return auto_config (dz_dev.name, ndev); /* auto config */ } /* SHOW VECTOR processor */ @@ -678,10 +714,10 @@ t_stat dz_show_log (FILE *st, UNIT *uptr, int32 val, void *desc) int32 i; for (i = 0; i < dz_desc.lines; i++) { - fprintf (st, "line %d: ", i); - tmxr_show_log (st, NULL, i, desc); - fprintf (st, "\n"); - } + fprintf (st, "line %d: ", i); + tmxr_show_log (st, NULL, i, desc); + fprintf (st, "\n"); + } return SCPE_OK; } diff --git a/PDP11/pdp11_fp.c b/PDP11/pdp11_fp.c index 27abae2c..4c36c41a 100644 --- a/PDP11/pdp11_fp.c +++ b/PDP11/pdp11_fp.c @@ -1,6 +1,6 @@ /* pdp11_fp.c: PDP-11 floating point simulator (32b version) - Copyright (c) 1993-2004, Robert M Supnik + Copyright (c) 1993-2005, 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"), @@ -19,49 +19,49 @@ 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 + 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-04 RMS Added FIS instructions - 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 - + 04-Oct-04 RMS Added FIS instructions + 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 + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ 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 + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ 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 + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ 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_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_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_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 @@ -77,122 +77,122 @@ 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 + 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 + 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) +#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 */ +#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 */ +#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 - +#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 + 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 + 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 + 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 + 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))) + (((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 + 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 + 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 + 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) + 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 + 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 + 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) + +#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 cpu_type; @@ -211,14 +211,15 @@ 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 }; + 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); @@ -240,7 +241,7 @@ extern int32 GeteaW (int32 spec); extern int32 ReadW (int32 addr); extern void WriteW (int32 data, int32 addr); extern void set_stack_trap (int32 adr); - + /* Set up for instruction decode and execution */ void fp11 (int32 IR) @@ -249,311 +250,352 @@ int32 dst, ea, ac, dstspec; int32 i, qdouble, lenf, leni; int32 newV, exp, sign; fpac_t fac, fsrc, modfrac; -static const uint32 i_limit[2][2] = - { { 0x80000000, 0x80010000 }, { 0x80000000, 0x80000001 } }; +static const uint32 i_limit[2][2] = { + { 0x80000000, 0x80010000 }, { 0x80000000, 0x80000001 } + }; -backup_PC = PC; /* save PC for FEA */ -ac = (IR >> 6) & 03; /* fac is IR<7:6> */ +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 */ +switch ((IR >> 8) & 017) { /* decode IR<11:8> */ -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 000: + switch (ac) { /* decode IR<7:6> */ -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; + 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; -/* Load and store exponent instructions */ + case 1: /* LDFPS */ + dst = (dstspec <= 07)? R[dstspec]: ReadW (GeteaW (dstspec)); + FPS = dst & FPS_RW; + break; -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 2: /* STFPS */ + FPS = FPS & FPS_RW; + if (dstspec <= 07) R[dstspec] = FPS; + else WriteW (FPS, GeteaW (dstspec)); + break; -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 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 */ + + case 001: + 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 005: /* 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; + + case 007: /* 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; + + 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; + + 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; + + case 002: /* 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 003: /* 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 004: /* 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 006: /* 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); + if (GET_EXP (fsrc.h) == 0) { /* divide by zero? */ + fpnotrap (FEC_DZRO); + ABORT (TRAP_INT); + } + newV = divfp11 (&fac, &fsrc); + F_STORE (qdouble, fac, FR[ac]); + FPS = setfcc (FPS, fac.h, newV); + break; + } /* end switch fop */ -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); - if (GET_EXP (fsrc.h) == 0) { /* divide by zero? */ - fpnotrap (FEC_DZRO); - ABORT (TRAP_INT); } - 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 + spec = specifier + len = length Outputs: - VA = virtual address + VA = virtual address Warnings: - - Do not call this routine for integer mode 0 operands - - Do not call this routine more than once per instruction + - 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; -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 ((reg == 6) && (cm == MD_KER) && (adr < (STKLIM + STKL_Y))) - set_stack_trap (adr); - return (adr | ds); -case 5: /* @-(R) */ - adr = R[reg] = (R[reg] - 2) & 0177777; - if (update_MM) MMR1 = 0360 | reg; - if ((reg == 6) && (cm == MD_KER) && (adr < (STKLIM + STKL_Y))) - set_stack_trap (adr); - 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 */ +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 ((reg == 6) && (cm == MD_KER) && (adr < (STKLIM + STKL_Y))) + set_stack_trap (adr); + return (adr | ds); + + case 5: /* @-(R) */ + adr = R[reg] = (R[reg] - 2) & 0177777; + if (update_MM) MMR1 = 0360 | reg; + if ((reg == 6) && (cm == MD_KER) && (adr < (STKLIM + STKL_Y))) + set_stack_trap (adr); + 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) + 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 + data = data read from memory or I/O space */ uint32 ReadI (int32 VA, int32 spec, int32 len) @@ -565,10 +607,10 @@ 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) + 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) @@ -576,30 +618,34 @@ 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; } + 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; } + 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); + (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 + data = data to be written + VA = virtual address, VA<18:16> = mode, I/D space + spec = specifier + len = length Outputs: none */ @@ -614,10 +660,10 @@ 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 + fptr = pointer to data to be written + VA = virtual address, VA<18:16> = mode, I/D space + spec = specifier + len = length Outputs: none */ @@ -626,8 +672,9 @@ 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; } + F_STORE_P (len == QUAD, fptr, FR[spec]); + return; + } WriteW ((fptr->h >> FP_V_F0) & 0177777, VA); if (spec == 027) return; exta = VA & ~0177777; @@ -637,7 +684,7 @@ WriteW ((fptr->l >> FP_V_F2) & 0177777, exta | ((VA + 4) & 0177777)); WriteW ((fptr->l >> FP_V_F3) & 0177777, exta | ((VA + 6) & 0177777)); return; } - + /* FIS instructions */ t_stat fis11 (int32 IR) @@ -645,66 +692,73 @@ t_stat fis11 (int32 IR) int32 reg, exta; fpac_t fac, fsrc; -reg = IR & 07; /* isolate reg */ -if (reg == 7) exta = isenable; /* choose I,D */ +reg = IR & 07; /* isolate reg */ +if (reg == 7) exta = isenable; /* choose I,D */ else exta = dsenable; -if (IR & 000740) { /* defined? */ - if (CPUT (CPUT_03)) ReadW (exta | R[reg]); /* 11/03 reads word */ - ABORT (TRAP_ILL); } -FEC = 0; /* no errors */ -FPS = FPS_IU|FPS_IV; /* trap ovf,unf */ +if (IR & 000740) { /* defined? */ + if (CPUT (CPUT_03)) ReadW (exta | R[reg]); /* 11/03 reads word */ + ABORT (TRAP_ILL); + } +FEC = 0; /* no errors */ +FPS = FPS_IU|FPS_IV; /* trap ovf,unf */ fsrc.h = (ReadW (exta | R[reg]) << FP_V_F0) | - (ReadW (exta | ((R[reg] + 2) & 0177777)) << FP_V_F1); + (ReadW (exta | ((R[reg] + 2) & 0177777)) << FP_V_F1); fsrc.l = 0; fac.h = (ReadW (exta | ((R[reg] + 4) & 0177777)) << FP_V_F0) | - (ReadW (exta | ((R[reg] + 6) & 0177777)) << FP_V_F1); + (ReadW (exta | ((R[reg] + 6) & 0177777)) << FP_V_F1); fac.l = 0; -if (GET_SIGN (fsrc.h) && (GET_EXP (fsrc.h) == 0)) /* clean 0's */ - fsrc.h = fsrc.l = 0; +if (GET_SIGN (fsrc.h) && (GET_EXP (fsrc.h) == 0)) /* clean 0's */ + fsrc.h = fsrc.l = 0; if (GET_SIGN (fac.h) && (GET_EXP (fac.l) == 0)) - fac.h = fac.l = 0; + fac.h = fac.l = 0; -N = Z = V = C = 0; /* clear cc's */ -switch ((IR >> 3) & 3) { /* case IR<5:3> */ +N = Z = V = C = 0; /* clear cc's */ +switch ((IR >> 3) & 3) { /* case IR<5:3> */ -case 0: /* FAD */ - addfp11 (&fac, &fsrc); - break; -case 1: /* FSUB */ - if (fsrc.h != 0) fsrc.h = fsrc.h ^ FP_SIGN; /* invert sign */ - addfp11 (&fac, &fsrc); - break; -case 2: /* FMUL */ - mulfp11 (&fac, &fsrc); - break; -case 3: /* FDIV */ - if (fsrc.h == 0) { /* div by 0? */ - V = N = C = 1; /* set cc's */ - setTRAP (TRAP_FPE); /* set trap */ - return SCPE_OK; } - else divfp11 (&fac, &fsrc); - break; } + case 0: /* FAD */ + addfp11 (&fac, &fsrc); + break; -if (FEC == 0) { /* no err? */ - WriteW ((fac.h >> FP_V_F0) & 0177777, exta | ((R[reg] + 4) & 0177777)); - WriteW ((fac.h >> FP_V_F1) & 0177777, exta | ((R[reg] + 6) & 0177777)); - R[reg] = (R[reg] + 4) & 0177777; /* pop stack */ - N = (GET_SIGN (fac.h) != 0); /* set N,Z */ - Z = (fac.h == 0); } -else if (FEC == FEC_OVFLO) V = 1; /* ovf? trap set */ -else if (FEC == FEC_UNFLO) V = N = 1; /* unf? trap set */ -else return SCPE_IERR; /* what??? */ + case 1: /* FSUB */ + if (fsrc.h != 0) fsrc.h = fsrc.h ^ FP_SIGN; /* invert sign */ + addfp11 (&fac, &fsrc); + break; + + case 2: /* FMUL */ + mulfp11 (&fac, &fsrc); + break; + + case 3: /* FDIV */ + if (fsrc.h == 0) { /* div by 0? */ + V = N = C = 1; /* set cc's */ + setTRAP (TRAP_FPE); /* set trap */ + return SCPE_OK; + } + else divfp11 (&fac, &fsrc); + break; + } + +if (FEC == 0) { /* no err? */ + WriteW ((fac.h >> FP_V_F0) & 0177777, exta | ((R[reg] + 4) & 0177777)); + WriteW ((fac.h >> FP_V_F1) & 0177777, exta | ((R[reg] + 6) & 0177777)); + R[reg] = (R[reg] + 4) & 0177777; /* pop stack */ + N = (GET_SIGN (fac.h) != 0); /* set N,Z */ + Z = (fac.h == 0); + } +else if (FEC == FEC_OVFLO) V = 1; /* ovf? trap set */ +else if (FEC == FEC_UNFLO) V = N = 1; /* unf? trap set */ +else return SCPE_IERR; /* what??? */ return SCPE_OK; } - + /* Floating point add Inputs: - facp = pointer to src1 (output) - fsrcp = pointer to src2 + facp = pointer to src1 (output) + fsrcp = pointer to src2 Outputs: - ovflo = overflow variable + ovflo = overflow variable */ int32 addfp11 (fpac_t *facp, fpac_t *fsrcp) @@ -712,56 +766,70 @@ 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 */ +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 */ +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 (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; } } +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 + facp = pointer to src1 (output) + fsrcp = pointer to src2 Outputs: - ovflo = overflow indicator + ovflo = overflow indicator */ int32 mulfp11 (fpac_t *facp, fpac_t *fsrcp) @@ -769,16 +837,17 @@ int32 mulfp11 (fpac_t *facp, fpac_t *fsrcp) int32 facexp, fsrcexp; fpac_t facfrac, fsrcfrac; -facexp = GET_EXP (facp->h); /* get exponents */ +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 */ +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 */ +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 @@ -786,19 +855,20 @@ frac_mulfp11 (&facfrac, &fsrcfrac); /* multiply fracs */ */ if (GET_BIT (facfrac.h, FP_V_HB + FP_GUARD) == 0) { - F_LSH_1 (facfrac); - facexp = facexp - 1; } + 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 + facp = pointer to src1 (integer result) + fsrcp = pointer to src2 + fracp = pointer to fractional result Outputs: - ovflo = overflow indicator + ovflo = overflow indicator See notes on multiply for initial operation */ @@ -808,17 +878,18 @@ 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 */ +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 */ +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 */ +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 @@ -826,9 +897,10 @@ frac_mulfp11 (&facfrac, &fsrcfrac); /* multiply fracs */ */ if (GET_BIT (facfrac.h, FP_V_HB + FP_GUARD) == 0) { - F_LSH_1 (facfrac); - facexp = facexp - 1; } - + 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 @@ -839,42 +911,49 @@ if (GET_BIT (facfrac.h, FP_V_HB + FP_GUARD) == 0) { 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); +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 + f1p = pointer to multiplier (output) + f2p = pointer to multiplicand fraction Note: the inputs are unguarded; the output is guarded. @@ -900,35 +979,46 @@ 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 */ +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; } } +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 + facp = pointer to dividend (output) + fsrcp = pointer to divisor Outputs: - ovflo = overflow indicator + ovflo = overflow indicator Source operand must be checked for zero by caller! */ @@ -938,29 +1028,34 @@ 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 */ -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 */ +fsrcexp = GET_EXP (fsrcp->h); /* get divisor exp */ +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 (facfrac); /* guard fractions */ F_LSH_GUARD (fsrcfrac); -facexp = facexp - fsrcexp + FP_BIAS + 1; /* calculate exp */ -facp->h = facp->h ^ fsrcp->h; /* calculate sign */ +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 */ +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? */ + 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) { /* early exit? */ + F_LSH_V (quo, i, quo); + } /* 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 @@ -969,20 +1064,21 @@ if (i > 0) { F_LSH_V (quo, i, quo); } /* early exit? */ */ if (GET_BIT (quo.h, FP_V_HB + FP_GUARD) == 0) { - F_LSH_1 (quo); - facexp = facexp - 1; } + 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 + oldst = current status + result = high result + newV = new V Outputs: - newst = new status + newst = new status */ int32 setfcc (int32 oldst, int32 result, int32 newV) @@ -996,56 +1092,64 @@ return oldst; /* Round (in place) floating point number to f_floating Inputs: - fptr = pointer to floating number + fptr = pointer to floating number Outputs: - ovflow = overflow + 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 */ +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 */ + } +*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) + 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 + ovflo = overflow indicator */ int32 round_and_pack (fpac_t *facp, int32 exp, fpac_t *fracp, int r) { fpac_t frac; -frac = *fracp; /* get fraction */ +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; } } + 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); + (frac.h & FP_FRACH); if (exp > 0377) { - if (fpnotrap (FEC_OVFLO)) *facp = zero_fac; - return FPS_V; } + if (fpnotrap (FEC_OVFLO)) *facp = zero_fac; + return FPS_V; + } if ((exp <= 0) && (fpnotrap (FEC_UNFLO))) *facp = zero_fac; return 0; } @@ -1053,9 +1157,9 @@ return 0; /* Process floating point exception Inputs: - code = exception code + code = exception code Outputs: - int = FALSE if interrupt enabled, TRUE if disabled + int = FALSE if interrupt enabled, TRUE if disabled */ int32 fpnotrap (int32 code) diff --git a/PDP11/pdp11_hk.c b/PDP11/pdp11_hk.c index bb7e1527..e612be20 100644 --- a/PDP11/pdp11_hk.c +++ b/PDP11/pdp11_hk.c @@ -19,20 +19,22 @@ 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 + 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 + hk RK611/RK06/RK07 disk - 18-Mar-05 RMS Added attached test to detach routine - 03-Oct-04 RMS Revised Unibus interface - RMS Fixed state of output ready for M+ - 26-Mar-04 RMS Fixed warnings with -std=c99 - 25-Jan-04 RMS Revised for device debug support - 04-Jan-04 RMS Changed sim_fsize calling sequence - 29-Dec-03 RMS Added 18b Qbus support - 25-Apr-03 RMS Revised for extended file support + 16-Aug-05 RMS Fixed C++ declaration and cast problems + 07-Jul-05 RMS Removed extraneous externs + 18-Mar-05 RMS Added attached test to detach routine + 03-Oct-04 RMS Revised Unibus interface + RMS Fixed state of output ready for M+ + 26-Mar-04 RMS Fixed warnings with -std=c99 + 25-Jan-04 RMS Revised for device debug support + 04-Jan-04 RMS Changed sim_fsize calling sequence + 29-Dec-03 RMS Added 18b Qbus support + 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, @@ -45,296 +47,295 @@ This module includes ideas from a previous implementation by Fred Van Kempen. */ - -#if defined (VM_PDP10) /* PDP10 version */ + +#if defined (VM_PDP10) /* PDP10 version */ #error "RK611 is not supported on the PDP-10!" -#elif defined (VM_VAX) /* VAX version */ +#elif defined (VM_VAX) /* VAX version */ #include "vax_defs.h" -#else /* PDP-11 version */ +#else /* PDP-11 version */ #include "pdp11_defs.h" extern int32 cpu_opt; #endif 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) +#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 */ +#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 */ +#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)) +#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 */ +#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) +#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) +#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 +#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 */ +#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 */ +#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)) +#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)) +#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 +#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 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 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 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 A2_V_DIF 4 /* cyl diff */ +#define A2_M_DIF 0777 -#define A3_V_SNO 3 /* serial # */ +#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 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 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 B2_V_CYL 4 /* cylinder */ -#define B3_V_SEC 4 /* sector */ -#define B3_V_DHA 9 /* decoded head */ +#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 */ - +#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 FILE *sim_deb; -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 */ +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 */ +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 }; @@ -356,247 +357,289 @@ 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 + 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 } }; +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) } }; + { 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, DEV_RDX, 16, 0) }, - { GRDATA (HKWC, hkwc, DEV_RDX, 16, 0) }, - { GRDATA (HKBA, hkba, DEV_RDX, 16, 0) }, - { GRDATA (HKDA, hkda, DEV_RDX, 16, 0) }, - { GRDATA (HKCS2, hkcs2, DEV_RDX, 16, 0) }, - { BRDATA (HKDS, hkds, DEV_RDX, 16, HK_NUMDR) }, - { BRDATA (HKER, hker, DEV_RDX, 16, HK_NUMDR) }, - { BRDATA (HKDB, hkdb, DEV_RDX, 16, 3) }, - { GRDATA (HKDC, hkdc, DEV_RDX, 16, 0) }, - { GRDATA (HKOF, hkof, DEV_RDX, 8, 0) }, - { GRDATA (HKMR, hkmr, DEV_RDX, 16, 0) }, - { GRDATA (HKMR2, hkmr2, DEV_RDX, 16, 0), REG_RO }, - { GRDATA (HKMR3, hkmr3, DEV_RDX, 16, 0), REG_RO }, - { GRDATA (HKSPR, hkspr, DEV_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, DEV_RDX, 5, 0, - HK_NUMDR, REG_HRO) }, - { URDATA (CYL, hk_unit[0].CYL, DEV_RDX, 10, 0, - HK_NUMDR, REG_HRO) }, - { BRDATA (OFFSET, hk_off, DEV_RDX, 16, HK_NUMDR), REG_HRO }, - { BRDATA (CYLDIF, hk_dif, DEV_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, DEV_RDX, 32, 0), REG_HRO }, - { GRDATA (DEVVEC, hk_dib.vec, DEV_RDX, 16, 0), REG_HRO }, - { NULL } }; + { GRDATA (HKCS1, hkcs1, DEV_RDX, 16, 0) }, + { GRDATA (HKWC, hkwc, DEV_RDX, 16, 0) }, + { GRDATA (HKBA, hkba, DEV_RDX, 16, 0) }, + { GRDATA (HKDA, hkda, DEV_RDX, 16, 0) }, + { GRDATA (HKCS2, hkcs2, DEV_RDX, 16, 0) }, + { BRDATA (HKDS, hkds, DEV_RDX, 16, HK_NUMDR) }, + { BRDATA (HKER, hker, DEV_RDX, 16, HK_NUMDR) }, + { BRDATA (HKDB, hkdb, DEV_RDX, 16, 3) }, + { GRDATA (HKDC, hkdc, DEV_RDX, 16, 0) }, + { GRDATA (HKOF, hkof, DEV_RDX, 8, 0) }, + { GRDATA (HKMR, hkmr, DEV_RDX, 16, 0) }, + { GRDATA (HKMR2, hkmr2, DEV_RDX, 16, 0), REG_RO }, + { GRDATA (HKMR3, hkmr3, DEV_RDX, 16, 0), REG_RO }, + { GRDATA (HKSPR, hkspr, DEV_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, DEV_RDX, 5, 0, + HK_NUMDR, REG_HRO) }, + { URDATA (CYL, hk_unit[0].CYL, DEV_RDX, 10, 0, + HK_NUMDR, REG_HRO) }, + { BRDATA (OFFSET, hk_off, DEV_RDX, 16, HK_NUMDR), REG_HRO }, + { BRDATA (CYLDIF, hk_dif, DEV_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, DEV_RDX, 32, 0), REG_HRO }, + { GRDATA (DEVVEC, hk_dib.vec, DEV_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 } }; + { 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, DEV_RDX, 24, 1, DEV_RDX, 16, - NULL, NULL, &hk_reset, - &hk_boot, &hk_attach, &hk_detach, - &hk_dib, DEV_DISABLE | DEV_UBUS | DEV_Q18 | DEV_DEBUG }; - + "HK", hk_unit, hk_reg, hk_mod, + HK_NUMDR, DEV_RDX, 24, 1, DEV_RDX, 16, + NULL, NULL, &hk_reset, + &hk_boot, &hk_attach, &hk_detach, + &hk_dib, DEV_DISABLE | DEV_UBUS | DEV_Q18 | DEV_DEBUG + }; + /* 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; } +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; + 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; + } -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; - 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? */ +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; } + 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 = 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; - 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 */ +switch (j) { /* decode PA<4:1> */ + + case 000: /* HKCS1 */ + if (data & CS1_CCLR) { /* controller reset? */ + hkcs1 = CS1_DONE; /* CS1 = done */ + hkcs2 = CS2_IR; /* 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; + 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) @@ -605,89 +648,100 @@ 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 }; + 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 }; + 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 }; + 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 }; + 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0 + }; fnc = GET_FNC (hkcs1); if (DEBUG_PRS (hk_dev)) fprintf (sim_deb, - ">>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? */ + ">>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; } + 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 */ +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; + 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; + 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; + 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; } + default: + hk_cmderr (ER_ILF, drv); /* not supported */ + break; + } return; } - + /* Service unit timeout Complete movement or data transfer command @@ -702,160 +756,181 @@ 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 */ +drv = (int32) (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_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_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; + 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_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; + 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_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 */ + 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; } } + 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)) { /* 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)) { /* 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])) { - wc = 0; /* NXM, no xfr */ - hkcs2 = hkcs2 | CS2_NEM; } } /* set nxm err */ - else { /* normal */ - if (t = Map_WriteW (ba, wc << 1, hkxb)) { /* 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)) { /* 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 */ + 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)) { /* 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)) { /* 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])) { + wc = 0; /* NXM, no xfr */ + hkcs2 = hkcs2 | CS2_NEM; /* set nxm err */ + } + } + else { /* normal */ + if (t = Map_WriteW (ba, wc << 1, hkxb)) { /* 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)) { /* 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; + 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; } + 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 */ -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 @@ -868,17 +943,19 @@ 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); } +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 */ +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; } @@ -887,19 +964,23 @@ return; void update_hkds (int32 drv) { -if (hk_unit[drv].flags & UNIT_DIS) { /* disabled? */ - hkds[drv] = hker[drv] = 0; /* all clear */ - return; } +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_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; } @@ -908,13 +989,13 @@ return; 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 */ +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 @@ -924,12 +1005,13 @@ 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 */ +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; } @@ -941,35 +1023,44 @@ 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; } + + 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); } @@ -979,26 +1070,32 @@ 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; } + + 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) @@ -1006,23 +1103,24 @@ t_stat hk_reset (DEVICE *dptr) int32 i; UNIT *uptr; -hkcs1 = CS1_DONE; /* set done */ -hkcs2 = CS2_IR; /* clear state */ +hkcs1 = CS1_DONE; /* set done */ +hkcs2 = CS2_IR; /* 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 (uint16)); +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 = (uint16 *) calloc (HK_MAXFR, sizeof (uint16)); if (hkxb == NULL) return SCPE_MEM; return SCPE_OK; } @@ -1035,25 +1133,29 @@ 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 */ +r = attach_unit (uptr, cptr); /* attach unit */ +if (r != SCPE_OK) return r; /* error? */ +drv = (int32) (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 */ +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 */ +update_hkcs (CS1_DI, drv); /* upd ctlr status */ -if ((p = sim_fsize (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 = sim_fsize (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; } + uptr->flags = uptr->flags | UNIT_RK07; + uptr->capac = RK07_SIZE; + } +else { + uptr->flags = uptr->flags & ~UNIT_RK07; + uptr->capac = RK06_SIZE; + } return SCPE_OK; } @@ -1063,15 +1165,16 @@ t_stat hk_detach (UNIT *uptr) { int32 drv; -if (!(uptr->flags & UNIT_ATT)) return SCPE_OK; /* attached? */ -drv = uptr - hk_dev.units; /* get drv number */ +if (!(uptr->flags & UNIT_ATT)) return SCPE_OK; /* attached? */ +drv = (int32) (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 */ +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); } @@ -1095,44 +1198,44 @@ 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)) +#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 */ -}; + 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) { diff --git a/PDP11/pdp11_io.c b/PDP11/pdp11_io.c index 7e35181b..fdc9142f 100644 --- a/PDP11/pdp11_io.c +++ b/PDP11/pdp11_io.c @@ -1,6 +1,6 @@ /* pdp11_io.c: PDP-11 I/O simulator - Copyright (c) 1993-2004, Robert M Supnik + Copyright (c) 1993-2005, 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"), @@ -19,28 +19,29 @@ 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 + 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-Sep-04 RMS Revised Unibus interface - 28-May-04 RMS Revised I/O dispatching (from John Dundas) - 25-Jan-04 RMS Removed local debug logging support - 21-Dec-03 RMS Fixed bug in autoconfigure vector assignment; added controls - 21-Nov-03 RMS Added check for interrupt slot conflict (found by Dave Hittner) - 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 + 25-Jul-05 RMS Revised autoconfiguration algorithm and interface + 30-Sep-04 RMS Revised Unibus interface + 28-May-04 RMS Revised I/O dispatching (from John Dundas) + 25-Jan-04 RMS Removed local debug logging support + 21-Dec-03 RMS Fixed bug in autoconfigure vector assignment; added controls + 21-Nov-03 RMS Added check for interrupt slot conflict (found by Dave Hittner) + 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]; @@ -65,23 +66,24 @@ static t_stat (*iodispR[IOPAGESIZE >> 1])(int32 *dat, int32 ad, int32 md); static t_stat (*iodispW[IOPAGESIZE >> 1])(int32 dat, int32 ad, int32 md); static DIB *iodibp[IOPAGESIZE >> 1]; -int32 int_vec[IPL_HLVL][32]; /* int req to vector */ +int32 int_vec[IPL_HLVL][32]; /* int req to vector */ -int32 (*int_ack[IPL_HLVL][32])(void); /* int ack routines */ +int32 (*int_ack[IPL_HLVL][32])(void); /* int ack routines */ static const int32 pirq_bit[7] = { - INT_V_PIR1, INT_V_PIR2, INT_V_PIR3, INT_V_PIR4, - INT_V_PIR5, INT_V_PIR6, INT_V_PIR7 }; - + INT_V_PIR1, INT_V_PIR2, INT_V_PIR3, INT_V_PIR4, + INT_V_PIR5, INT_V_PIR6, INT_V_PIR7 + }; + /* 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 + *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 + status = SCPE_OK or SCPE_NXM */ t_stat iopageR (int32 *data, uint32 pa, int32 access) @@ -91,9 +93,10 @@ t_stat stat; idx = (pa & IOPAGEMASK) >> 1; if (iodispR[idx]) { - stat = iodispR[idx] (data, pa, access); - trap_req = calc_ints (ipl, trap_req); - return stat; } + stat = iodispR[idx] (data, pa, access); + trap_req = calc_ints (ipl, trap_req); + return stat; + } return SCPE_NXM; } @@ -104,9 +107,10 @@ t_stat stat; idx = (pa & IOPAGEMASK) >> 1; if (iodispW[idx]) { - stat = iodispW[idx] (data, pa, access); - trap_req = calc_ints (ipl, trap_req); - return stat; } + stat = iodispW[idx] (data, pa, access); + trap_req = calc_ints (ipl, trap_req); + return stat; + } return SCPE_NXM; } @@ -117,7 +121,8 @@ 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); } + if (int_req[i]) return (trq | TRAP_INT); + } return (trq & ~TRAP_INT); } @@ -127,20 +132,20 @@ 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]; - return vec; /* return vector */ - } /* end if t */ - } /* end for j */ - } /* end for i */ +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]; + 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 @@ -156,47 +161,51 @@ t_stat ubm_rd (int32 *data, int32 addr, int32 access) int32 pg = (addr >> 2) & UBM_M_PN; *data = (addr & 2)? ((ub_map[pg] >> 16) & 077): - (ub_map[pg] & 0177776); + (ub_map[pg] & 0177776); return SCPE_OK; } t_stat ubm_wr (int32 data, int32 addr, int32 access) { 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); } + 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; } - + /* Mapped memory access routines for DMA devices */ -#define BUSMASK ((UNIBUS)? UNIMASK: PAMASK) +#define BUSMASK ((UNIBUS)? UNIMASK: PAMASK) /* Map I/O address to memory address - caller checks cpu_bme */ uint32 Map_Addr (uint32 ba) { -int32 pg = UBM_GETPN (ba); /* map entry */ -int32 off = UBM_GETOFF (ba); /* offset */ +int32 pg = UBM_GETPN (ba); /* map entry */ +int32 off = UBM_GETOFF (ba); /* offset */ -if (pg != UBM_M_PN) /* last page? */ - uba_last = (ub_map[pg] + off) & PAMASK; /* no, use map */ -else uba_last = (IOPAGEBASE + off) & PAMASK; /* yes, use fixed */ +if (pg != UBM_M_PN) /* last page? */ + uba_last = (ub_map[pg] + off) & PAMASK; /* no, use map */ +else uba_last = (IOPAGEBASE + off) & PAMASK; /* yes, use fixed */ return uba_last; } /* 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 + 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 These routines are used only for Unibus and Qbus devices. Massbus devices have their own IO routines. As a result, @@ -215,99 +224,115 @@ int32 Map_ReadB (uint32 ba, int32 bc, uint8 *buf) { uint32 alim, lim, ma; -ba = ba & BUSMASK; /* trim address */ +ba = ba & BUSMASK; /* trim address */ lim = ba + bc; -if (cpu_bme) { /* map enabled? */ - for ( ; ba < lim; ba++) { /* by bytes */ - ma = Map_Addr (ba); /* 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); } +if (cpu_bme) { /* map enabled? */ + for ( ; ba < lim; ba++) { /* by bytes */ + ma = Map_Addr (ba); /* 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) { uint32 alim, lim, ma; -ba = (ba & BUSMASK) & ~01; /* trim, align addr */ +ba = (ba & BUSMASK) & ~01; /* trim, align addr */ lim = ba + (bc & ~01); -if (cpu_bme) { /* map enabled? */ - for (; ba < lim; ba = ba + 2) { /* by words */ - ma = Map_Addr (ba); /* 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); } +if (cpu_bme) { /* map enabled? */ + for (; ba < lim; ba = ba + 2) { /* by words */ + ma = Map_Addr (ba); /* 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) { uint32 alim, lim, ma; -ba = ba & BUSMASK; /* trim address */ +ba = ba & BUSMASK; /* trim address */ lim = ba + bc; -if (cpu_bme) { /* map enabled? */ - for ( ; ba < lim; ba++) { /* by bytes */ - ma = Map_Addr (ba); /* 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); } +if (cpu_bme) { /* map enabled? */ + for ( ; ba < lim; ba++) { /* by bytes */ + ma = Map_Addr (ba); /* 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) { uint32 alim, lim, ma; -ba = (ba & BUSMASK) & ~01; /* trim, align addr */ +ba = (ba & BUSMASK) & ~01; /* trim, align addr */ lim = ba + (bc & ~01); -if (cpu_bme) { /* map enabled? */ - for (; ba < lim; ba = ba + 2) { /* by words */ - ma = Map_Addr (ba); /* 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); } +if (cpu_bme) { /* map enabled? */ + for (; ba < lim; ba = ba + 2) { /* by words */ + ma = Map_Addr (ba); /* map addr */ + if (!ADDR_IS_MEM (ma)) return (lim - ba); /* NXM? err */ + M[ma >> 1] = *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 = ba + 2) { /* by words */ + M[ba >> 1] = *buf++; + } + return (lim - alim); + } } - + /* Enable/disable autoconfiguration */ t_stat set_autocon (UNIT *uptr, int32 val, char *cptr, void *desc) { if (cptr != NULL) return SCPE_ARG; autcon_enb = val; -return auto_config (0, 0); +return auto_config (NULL, 0); } /* Show autoconfiguration status */ @@ -333,13 +358,13 @@ 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 */ -autcon_enb = 0; /* autoconfig off */ +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 */ +autcon_enb = 0; /* autoconfig off */ return SCPE_OK; } @@ -357,7 +382,7 @@ 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); + fprintf (st, "-%08o", dibp->ba + dibp->lnt - 1); if (dptr->flags & DEV_FLTA) fprintf (st, "*"); return SCPE_OK; } @@ -372,8 +397,8 @@ 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 */ +dptr->flags = dptr->flags | DEV_FLTA; /* floating */ +return auto_config (NULL, 0); /* autoconfigure */ } /* Change device vector */ @@ -396,8 +421,8 @@ 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; -dptr->flags = dptr->flags & ~DEV_FLTA; /* not floating */ -autcon_enb = 0; /* autoconfig off */ +dptr->flags = dptr->flags & ~DEV_FLTA; /* not floating */ +autcon_enb = 0; /* autoconfig off */ return SCPE_OK; } @@ -418,25 +443,30 @@ 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))); } +else { + fprintf (st, "vector=%o", vec); + if (numvec > 1) fprintf (st, "-%o", vec + (4 * (numvec - 1))); + } return SCPE_OK; } - + /* Init Unibus tables */ void init_ubus_tab (void) { int32 i, j; -for (i = 0; i < IPL_HLVL; i++) { /* clear intr tab */ - for (j = 0; j < 32; j++) { - int_vec[i][j] = 0; - int_ack[i][j] = NULL; } } -for (i = 0; i < (IOPAGESIZE >> 1); i++) { /* clear dispatch tab */ - iodispR[i] = NULL; - iodispW[i] = NULL; - iodibp[i] = NULL; } +for (i = 0; i < IPL_HLVL; i++) { /* clear intr tab */ + for (j = 0; j < 32; j++) { + int_vec[i][j] = 0; + int_ack[i][j] = NULL; + } + } +for (i = 0; i < (IOPAGESIZE >> 1); i++) { /* clear dispatch tab */ + iodispR[i] = NULL; + iodispW[i] = NULL; + iodibp[i] = NULL; + } return; } @@ -446,44 +476,44 @@ t_stat build_ubus_tab (DEVICE *dptr, DIB *dibp) { int32 i, idx, vec, ilvl, ibit; -if ((dptr == NULL) || (dibp == NULL)) return SCPE_IERR; /* validate args */ +if ((dptr == NULL) || (dibp == NULL)) return SCPE_IERR; /* validate args */ if (dibp->vnum > VEC_DEVMAX) return SCPE_IERR; -for (i = 0; i < dibp->vnum; i++) { /* loop thru vec */ - idx = dibp->vloc + i; /* vector index */ - vec = dibp->vec? (dibp->vec + (i * 4)): 0; /* vector addr */ - ilvl = idx / 32; - ibit = idx % 32; - if ((int_ack[ilvl][ibit] && dibp->ack[i] && /* conflict? */ - (int_ack[ilvl][ibit] != dibp->ack[i])) || - (int_vec[ilvl][ibit] && vec && - (int_vec[ilvl][ibit] != vec))) { - printf ("Device %s interrupt slot conflict at %d\n", - sim_dname (dptr), idx); - if (sim_log) fprintf (sim_log, - "Device %s interrupt slot conflict at %d\n", - sim_dname (dptr), idx); - return SCPE_STOP; - } - if (dibp->ack[i]) int_ack[ilvl][ibit] = dibp->ack[i]; - else if (vec) int_vec[ilvl][ibit] = vec; - } -for (i = 0; i < (int32) dibp->lnt; i = i + 2) { /* create entries */ - idx = ((dibp->ba + i) & IOPAGEMASK) >> 1; /* index into disp */ - if ((iodispR[idx] && dibp->rd && /* conflict? */ - (iodispR[idx] != dibp->rd)) || - (iodispW[idx] && dibp->wr && - (iodispW[idx] != dibp->wr))) { - 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 SCPE_STOP; - } - if (dibp->rd) iodispR[idx] = dibp->rd; /* set rd dispatch */ - if (dibp->wr) iodispW[idx] = dibp->wr; /* set wr dispatch */ - iodibp[idx] = dibp; /* remember DIB */ - } +for (i = 0; i < dibp->vnum; i++) { /* loop thru vec */ + idx = dibp->vloc + i; /* vector index */ + vec = dibp->vec? (dibp->vec + (i * 4)): 0; /* vector addr */ + ilvl = idx / 32; + ibit = idx % 32; + if ((int_ack[ilvl][ibit] && dibp->ack[i] && /* conflict? */ + (int_ack[ilvl][ibit] != dibp->ack[i])) || + (int_vec[ilvl][ibit] && vec && + (int_vec[ilvl][ibit] != vec))) { + printf ("Device %s interrupt slot conflict at %d\n", + sim_dname (dptr), idx); + if (sim_log) fprintf (sim_log, + "Device %s interrupt slot conflict at %d\n", + sim_dname (dptr), idx); + return SCPE_STOP; + } + if (dibp->ack[i]) int_ack[ilvl][ibit] = dibp->ack[i]; + else if (vec) int_vec[ilvl][ibit] = vec; + } +for (i = 0; i < (int32) dibp->lnt; i = i + 2) { /* create entries */ + idx = ((dibp->ba + i) & IOPAGEMASK) >> 1; /* index into disp */ + if ((iodispR[idx] && dibp->rd && /* conflict? */ + (iodispR[idx] != dibp->rd)) || + (iodispW[idx] && dibp->wr && + (iodispW[idx] != dibp->wr))) { + 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 SCPE_STOP; + } + if (dibp->rd) iodispR[idx] = dibp->rd; /* set rd dispatch */ + if (dibp->wr) iodispW[idx] = dibp->wr; /* set wr dispatch */ + iodibp[idx] = dibp; /* remember DIB */ + } return SCPE_OK; } @@ -496,24 +526,24 @@ DEVICE *dptr; DIB *dibp; t_stat r; -init_ubus_tab (); /* init Unibus tables */ -init_mbus_tab (); /* init Massbus tables */ -for (i = 0; i < 7; i++) /* seed PIRQ intr */ - int_vec[i + 1][pirq_bit[i]] = VEC_PIRQ; -if (r = cpu_build_dib ()) return r; /* build CPU entries */ -for (i = 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 (dptr->flags & DEV_MBUS) { /* Massbus? */ - if (r = build_mbus_tab (dptr, dibp)) /* add to Mbus tab */ - return r; - } - else { /* no, Unibus */ - if (r = build_ubus_tab (dptr, dibp)) /* add to Unibus tab */ - return r; - } - } /* end if enabled */ - } /* end for */ +init_ubus_tab (); /* init Unibus tables */ +init_mbus_tab (); /* init Massbus tables */ +for (i = 0; i < 7; i++) /* seed PIRQ intr */ + int_vec[i + 1][pirq_bit[i]] = VEC_PIRQ; +if (r = cpu_build_dib ()) return r; /* build CPU entries */ +for (i = 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 (dptr->flags & DEV_MBUS) { /* Massbus? */ + if (r = build_mbus_tab (dptr, dibp)) /* add to Mbus tab */ + return r; + } + else { /* no, Unibus */ + if (r = build_ubus_tab (dptr, dibp)) /* add to Unibus tab */ + return r; + } + } /* end if enabled */ + } /* end for */ return SCPE_OK; } @@ -525,117 +555,162 @@ uint32 i, j; DEVICE *dptr; DIB *dibp; -if (build_dib_tab ()) return SCPE_OK; /* build IO page */ -for (i = 0, dibp = NULL; i < (IOPAGESIZE >> 1); i++) { /* loop thru entries */ - if (iodibp[i] && (iodibp[i] != dibp)) { /* new block? */ - dibp = iodibp[i]; /* DIB for block */ - for (j = 0, dptr = NULL; sim_devices[j] != NULL; j++) { - if (((DIB*) sim_devices[j]->ctxt) == dibp) { - dptr = sim_devices[j]; /* locate device */ - break; - } /* end if */ - } /* end for j */ - fprintf (st, "%08o - %08o%c\t%s\n", /* print block entry */ - dibp->ba, dibp->ba + dibp->lnt - 1, - (dptr && (dptr->flags & DEV_FLTA))? '*': ' ', - dptr? sim_dname (dptr): "CPU"); - } /* end if */ - } /* end for i */ +if (build_dib_tab ()) return SCPE_OK; /* build IO page */ +for (i = 0, dibp = NULL; i < (IOPAGESIZE >> 1); i++) { /* loop thru entries */ + if (iodibp[i] && (iodibp[i] != dibp)) { /* new block? */ + dibp = iodibp[i]; /* DIB for block */ + for (j = 0, dptr = NULL; sim_devices[j] != NULL; j++) { + if (((DIB*) sim_devices[j]->ctxt) == dibp) { + dptr = sim_devices[j]; /* locate device */ + break; + } /* end if */ + } /* end for j */ + fprintf (st, "%08o - %08o%c\t%s\n", /* print block entry */ + dibp->ba, dibp->ba + dibp->lnt - 1, + (dptr && (dptr->flags & DEV_FLTA))? '*': ' ', + dptr? sim_dname (dptr): "CPU"); + } /* end if */ + } /* end for i */ return SCPE_OK; } - -/* Autoconfiguration */ -#define AUTO_DYN 0001 -#define AUTO_VEC 0002 -#define AUTO_MAXC 4 -#define AUTO_CSRBASE 0010 -#define AUTO_VECBASE 0300 +/* Autoconfiguration -struct auto_con { - uint32 amod; - uint32 vmod; - uint32 flags; - uint32 num; - uint32 fix; - char *dnam[AUTO_MAXC]; }; + The table reflects the MicroVAX 3900 microcode, with one addition - the + number of controllers field handles devices where multiple instances + are simulated through a single DEVICE structure (e.g., DZ, VH). -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" } }, + A minus number of vectors indicates a field that should be calculated + but not placed in the DIB (RQ, TQ dynamic vectors) */ - { 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 */ +#define AUTO_MAXC 4 +#define AUTO_CSRBASE 0010 +#define AUTO_VECBASE 0300 - { 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 */ +typedef struct { + char *dnam[AUTO_MAXC]; + int32 numc; + int32 numv; + uint32 amod; + uint32 vmod; + uint32 fixa[AUTO_MAXC]; + uint32 fixv[AUTO_MAXC]; + } AUTO_CON; - { 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 */ - { 0x1f, 0x7, AUTO_VEC, VH_MUXES, 0, { "VH" } }, /* DHU11/DHQ11 */ - - { 0x1f, 0x7 }, /* DMZ32 */ - { 0x1f, 0x7 }, /* CP132 */ - { 0 }, /* padding */ +AUTO_CON auto_tab[] = { + { { NULL }, 1, 2, 0, 8, { 0 } }, /* DLV11J - fx CSRs */ + { { NULL }, 1, 2, 8, 8 }, /* DJ11 */ + { { NULL }, 1, 2, 16, 8 }, /* DH11 */ + { { NULL }, 1, 2, 8, 8 }, /* DQ11 */ + { { NULL }, 1, 2, 8, 8 }, /* DU11 */ + { { NULL }, 1, 2, 8, 8 }, /* DUP11 */ + { { NULL }, 10, 2, 8, 8 }, /* LK11A */ + { { NULL }, 1, 2, 8, 8 }, /* DMC11 */ + { { "DZ" }, DZ_MUXES, 2, 8, 8 }, /* DZ11 */ + { { NULL }, 1, 2, 8, 8 }, /* KMC11 */ + { { NULL }, 1, 2, 8, 8 }, /* LPP11 */ + { { NULL }, 1, 2, 8, 8 }, /* VMV21 */ + { { NULL }, 1, 2, 16, 8 }, /* VMV31 */ + { { NULL }, 1, 2, 8, 8 }, /* DWR70 */ + { { "RL", "RLB" }, 1, 1, 8, 4, {IOBA_RL}, {VEC_RL} }, /* RL11 */ + { { "TS", "TSB", "TSC", "TSD" }, 1, 1, 0, 4, /* TS11 */ + {IOBA_TS, IOBA_TS + 4, IOBA_TS + 8, IOBA_TS + 12}, + {VEC_TS} }, + { { NULL }, 1, 2, 16, 8 }, /* LPA11K */ + { { NULL }, 1, 2, 8, 8 }, /* KW11C */ + { { NULL }, 1, 1, 8, 8 }, /* reserved */ + { { "RX", "RY" }, 1, 1, 8, 4, {IOBA_RX} , {VEC_RX} }, /* RX11/RX211 */ + { { NULL }, 1, 1, 8, 4 }, /* DR11W */ + { { NULL }, 1, 1, 8, 4, { 0, 0 }, { 0 } }, /* DR11B - fx CSRs,vec */ + { { NULL }, 1, 2, 8, 8 }, /* DMP11 */ + { { NULL }, 1, 2, 8, 8 }, /* DPV11 */ + { { NULL }, 1, 2, 8, 8 }, /* ISB11 */ + { { NULL }, 1, 2, 16, 8 }, /* DMV11 */ +// { { "XU", "XUB" }, 1, 1, 8, 4, {IOBA_XU}, {VEC_XU} }, /* DEUNA */ + { { "XQ", "XQB" }, 1, 1, 0, 4, /* DEQNA */ + {IOBA_XQ,IOBA_XQB}, {VEC_XQ} }, + { { "RQ", "RQB", "RQC", "RQD" }, 1, -1, 4, 4, /* RQDX3 */ + {IOBA_RQ}, {VEC_RQ} }, + { { NULL }, 1, 8, 32, 4 }, /* DMF32 */ + { { NULL }, 1, 2, 16, 8 }, /* KMS11 */ + { { NULL }, 1, 1, 16, 4 }, /* VS100 */ + { { "TQ", "TQB" }, 1, -1, 4, 4, {IOBA_TQ}, {VEC_TQ} }, /* TQK50 */ + { { NULL }, 1, 2, 16, 8 }, /* KMV11 */ + { { "VH" }, VH_MUXES, 2, 16, 8 }, /* DHU11/DHQ11 */ + { { NULL }, 1, 6, 32, 4 }, /* DMZ32 */ + { { NULL }, 1, 6, 32, 4 }, /* CP132 */ + { { NULL }, 1, 2, 64, 8, { 0 } }, /* QVSS - fx CSR */ + { { NULL }, 1, 1, 8, 4 }, /* VS31 */ + { { NULL }, 1, 1, 0, 4, { 0 } }, /* LNV11 - fx CSR */ + { { NULL }, 1, 1, 16, 4 }, /* LNV21/QPSS */ + { { NULL }, 1, 1, 8, 4, { 0 } }, /* QTA - fx CSR */ + { { NULL }, 1, 1, 8, 4 }, /* DSV11 */ + { { NULL }, 1, 2, 8, 8 }, /* CSAM */ + { { NULL }, 1, 2, 8, 8 }, /* ADV11C */ + { { NULL }, 1, 0, 8, 0 }, /* AAV11C */ + { { NULL }, 1, 2, 8, 8, { 0 }, { 0 } }, /* AXV11C - fx CSR,vec */ + { { NULL }, 1, 2, 4, 8, { 0 } }, /* KWV11C - fx CSR */ + { { NULL }, 1, 2, 8, 8, { 0 } }, /* ADV11D - fx CSR */ + { { NULL }, 1, 2, 8, 8, { 0 } }, /* AAV11D - fx CSR */ +/* { { "QDSS" }, 1, 3, 0, 16, {IOBA_QDSS} }, /* QDSS - fx CSR */ + { { NULL }, -1 } /* end table */ }; -t_stat auto_config (uint32 rank, uint32 nctrl) +t_stat auto_config (char *name, int32 nctrl) { uint32 csr = IOPAGEBASE + AUTO_CSRBASE; uint32 vec = VEC_Q + AUTO_VECBASE; -struct auto_con *autp; +AUTO_CON *autp; DEVICE *dptr; DIB *dibp; -int32 i, j, k; -extern DEVICE *find_dev (char *ptr); +uint32 j, k, vmask, amask; -if (autcon_enb == 0) return SCPE_OK; /* enabled? */ -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 */ +if (autcon_enb == 0) return SCPE_OK; /* enabled? */ +if (name) { /* updating? */ + if (nctrl < 0) return SCPE_ARG; + for (autp = auto_tab; autp->numc >= 0; autp++) { + for (j = 0; (j < AUTO_MAXC) && autp->dnam[j]; j++) { + if (strcmp (name, autp->dnam[j]) == 0) + autp->numc = nctrl; + } + } + } +for (autp = auto_tab; autp->numc >= 0; autp++) { /* loop thru table */ + if (autp->amod) { /* floating csr? */ + amask = autp->amod - 1; + csr = (csr + amask) & ~amask; /* align csr */ + } + 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 (dibp == NULL) return SCPE_IERR; /* not there??? */ + if (autp->amod) { /* dyn csr needed? */ + if (autp->fixa[k]) /* fixed csr avail? */ + dibp->ba = autp->fixa[k]; /* use it */ + else { /* no fixed left */ + dibp->ba = csr; /* set CSR */ + csr += (autp->numc * autp->amod); /* next CSR */ + } /* end else */ + } /* end if dyn csr */ + if (autp->numv && autp->vmod) { /* dyn vec needed? */ + uint32 numv = abs (autp->numv); /* get num vec */ + if (autp->fixv[k]) { /* fixed vec avail? */ + if (autp->numv > 0) + dibp->vec = autp->fixv[k]; /* use it */ + } + else { /* no fixed left */ + vmask = autp->vmod - 1; + vec = (vec + vmask) & ~vmask; /* align vector */ + if (autp->numv > 0) + dibp->vec = vec; /* set vector */ + vec += (autp->numc * numv * 4); + } /* end else */ + } /* end if dyn vec */ + k++; /* next instance */ + } /* end for j */ + if (autp->amod) csr = csr + 2; /* flt CSR? gap */ + } /* end for i */ return SCPE_OK; } diff --git a/PDP11/pdp11_lp.c b/PDP11/pdp11_lp.c index 7dc92c4d..084bf8e6 100644 --- a/PDP11/pdp11_lp.c +++ b/PDP11/pdp11_lp.c @@ -1,6 +1,6 @@ /* pdp11_lp.c: PDP-11 line printer simulator - Copyright (c) 1993-2004, Robert M Supnik + Copyright (c) 1993-2005, 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"), @@ -19,41 +19,41 @@ 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 + 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 + 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 + 07-Jul-05 RMS Removed extraneous externs + 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 */ +#if defined (VM_PDP10) /* PDP10 version */ #error "LP11 is not supported on the PDP-10!" -#elif defined (VM_VAX) /* VAX version */ +#elif defined (VM_VAX) /* VAX version */ #include "vax_defs.h" -#else /* PDP-11 version */ +#else /* PDP-11 version */ #include "pdp11_defs.h" #endif -#define LPTCSR_IMP (CSR_ERR + CSR_DONE + CSR_IE) /* implemented */ -#define LPTCSR_RW (CSR_IE) /* read/write */ +#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 */ +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); @@ -65,76 +65,85 @@ t_stat lpt_detach (UNIT *uptr); /* LPT data structures - lpt_dev LPT device descriptor - lpt_unit LPT unit descriptor - lpt_reg LPT register list + 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 } }; +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 }; + 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 } }; + { 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 } }; + { 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 }; - + "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 + 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 */ +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); } +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; } @@ -143,23 +152,24 @@ 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); + 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; } + 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 */ +sim_cancel (&lpt_unit); /* deactivate unit */ return SCPE_OK; } diff --git a/PDP11/pdp11_mscp.h b/PDP11/pdp11_mscp.h index 8af9dfdb..4590ed7a 100644 --- a/PDP11/pdp11_mscp.h +++ b/PDP11/pdp11_mscp.h @@ -1,6 +1,6 @@ /* pdp11_mscp.h: DEC MSCP and TMSCP definitionsn - Copyright (c) 2001-2004, Robert M Supnik + Copyright (c) 2001-2005, Robert M Supnik Derived from work by Stephen F. Shirron Permission is hereby granted, free of charge, to any person obtaining a @@ -20,495 +20,495 @@ 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 + 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 + 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 +#define _PDP11_MSCP_H_ 0 /* Misc constants */ -#define UID_DISK 2 /* disk class */ -#define UID_TAPE 3 /* tape class */ +#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 */ +#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 */ +#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 */ +#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) +#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 */ +#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 */ +#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 */ +#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 */ +#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 */ +#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 */ +#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 */ +#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_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 +#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_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 */ +#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 +#define ABO_LNT 16 +#define ABO_REFL 8 /* ref # */ +#define ABO_REFH 9 /* Avail packet - min size */ -#define AVL_LNT 12 +#define AVL_LNT 12 /* Erase packet - min size */ -#define ERS_LNT 12 +#define ERS_LNT 12 /* Erase gap - min size */ -#define ERG_LNT 12 +#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 +#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 +#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 +#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 */ +#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 */ +#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 */ +#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_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 */ +#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 +#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 +#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_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 */ +#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_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 */ +#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 +#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 +#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 */ +#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 +#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 +#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_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 */ +#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_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 */ +#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 +#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 */ +#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_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 +#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_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 */ +#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 +#define UNA_LNT 32 #endif diff --git a/PDP11/pdp11_pclk.c b/PDP11/pdp11_pclk.c index 512c2552..f1ee1c54 100644 --- a/PDP11/pdp11_pclk.c +++ b/PDP11/pdp11_pclk.c @@ -1,6 +1,6 @@ /* pdp11_pclk.c: KW11P programmable clock simulator - Copyright (c) 1993-2004, Robert M Supnik + Copyright (c) 1993-2005, Robert M Supnik Written by John Dundas, used with his gracious permission Permission is hereby granted, free of charge, to any person obtaining a @@ -20,24 +20,25 @@ 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 + 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 -*/ + pclk KW11P line frequency clock -/* KW11-P Programmable Clock + 07-Jul-05 RMS Removed extraneous externs + + KW11-P Programmable Clock I/O Page Registers: - CSR 17 772 540 - CSB 17 772 542 - CNT 17 772 544 + CSR 17 772 540 + CSB 17 772 542 + CNT 17 772 544 - Vector: 0104 + Vector: 0104 - Priority: BR6 + Priority: BR6 ** Theory of Operation ** @@ -59,11 +60,11 @@ 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 + 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. @@ -107,32 +108,31 @@ #include "pdp11_defs.h" -#define PCLKCSR_RDMASK 0100377 /* readable */ -#define PCLKCSR_WRMASK 0000137 /* writeable */ +#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) +#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) +#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 */ +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); @@ -141,69 +141,79 @@ 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 + 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 } }; +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 } }; + { 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 } }; + { 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 }; - + "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; } + + 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; } @@ -213,28 +223,34 @@ 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 */ + + 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; } @@ -242,18 +258,20 @@ return SCPE_OK; 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 */ +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; } @@ -263,9 +281,9 @@ 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 */ +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; } @@ -274,12 +292,12 @@ return SCPE_OK; t_stat pclk_reset (DEVICE *dptr) { -pclk_csr = 0; /* clear reg */ +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 */ +CLR_INT (PCLK); /* clear int */ +sim_cancel (&pclk_unit); /* cancel */ +pclk_unit.wait = xtim[0]; /* reset delay */ return SCPE_OK; } diff --git a/PDP11/pdp11_pt.c b/PDP11/pdp11_pt.c index 34dc1352..24875900 100644 --- a/PDP11/pdp11_pt.c +++ b/PDP11/pdp11_pt.c @@ -1,6 +1,6 @@ /* pdp11_pt.c: PC11 paper tape reader/punch simulator - Copyright (c) 1993-2004, Robert M Supnik + Copyright (c) 1993-2005, 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"), @@ -19,46 +19,44 @@ 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 + 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 + 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 + 07-Jul-05 RMS Removed extraneous externs + 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 */ +#if defined (VM_PDP10) /* PDP10 version */ #include "pdp10_defs.h" -#define PT_DIS DEV_DIS +#define PT_DIS DEV_DIS extern int32 int_req; -extern int32 int_vec[32]; -#elif defined (VM_VAX) /* VAX version */ +#elif defined (VM_VAX) /* VAX version */ #include "vax_defs.h" -#define PT_DIS DEV_DIS +#define PT_DIS DEV_DIS extern int32 int_req[IPL_HLVL]; -extern int32 int_vec[IPL_HLVL][32]; -#else /* PDP-11 version */ +#else /* PDP-11 version */ #include "pdp11_defs.h" -#define PT_DIS 0 +#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) +#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 */ +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); @@ -73,123 +71,144 @@ 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 + 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 } }; +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 }; + 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 } }; + { 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 } }; + { 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 }; + "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 + 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 } }; +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 }; + 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 } }; + { 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 } }; + { 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 }; - + "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 */ +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 */ +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 */ @@ -201,20 +220,22 @@ 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); + 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; } + 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) @@ -242,40 +263,48 @@ 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 */ +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 */ +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 */ @@ -285,16 +314,17 @@ 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); + 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; } + 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) @@ -303,7 +333,7 @@ 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 */ +sim_cancel (&ptp_unit); /* deactivate unit */ return SCPE_OK; } diff --git a/PDP11/pdp11_rh.c b/PDP11/pdp11_rh.c index 3957e9a7..14d94a26 100644 --- a/PDP11/pdp11_rh.c +++ b/PDP11/pdp11_rh.c @@ -1,6 +1,6 @@ /* pdp11_rh.c: PDP-11 Massbus adapter simulator - Copyright (c) 2004, Robert M Supnik + Copyright (c) 2005, 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"), @@ -19,11 +19,13 @@ 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 + 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. - rha, rhb RH11/RH70 Massbus adapter + rha, rhb RH11/RH70 Massbus adapter + + 07-Jul-05 RMS Removed extraneous externs WARNING: The interupt logic of the RH11/RH70 is unusual and must be simulated with great precision. The RH11 has an internal interrupt @@ -40,122 +42,120 @@ but the SC interrupt is. */ -#if defined (VM_PDP10) /* PDP10 version */ +#if defined (VM_PDP10) /* PDP10 version */ #error "PDP-10 uses pdp10_rp.c and pdp10_tu.c!" -#elif defined (VM_VAX) /* VAX version */ +#elif defined (VM_VAX) /* VAX version */ #error "VAX uses vax780_mba.c!" -#else /* PDP-11 version */ +#else /* PDP-11 version */ #include "pdp11_defs.h" #endif /* CS1 - base + 000 - control/status 1 */ -#define CS1_OF 0 -#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_XFER 024 /* >=? data xfr */ -#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 CS1_OF 0 +#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_XFER 024 /* >=? data xfr */ +#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) /* WC - base + 002 - word count */ -#define WC_OF 1 +#define WC_OF 1 /* BA - base + 004 - base address */ -#define BA_OF 2 -#define BA_MBZ 0000001 /* must be zero */ +#define BA_OF 2 +#define BA_MBZ 0000001 /* must be zero */ /* CS2 - base + 010 - control/status 2 */ -#define CS2_OF 3 -#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) +#define CS2_OF 3 +#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) /* DB - base + 022 - data buffer */ -#define DB_OF 4 +#define DB_OF 4 /* BAE - base + 050/34 - bus address extension */ -#define BAE_OF 5 -#define AE_M_MAE 0 /* addr ext pos */ -#define AE_V_MAE 077 /* addr ext mask */ -#define AE_MBZ 0177700 +#define BAE_OF 5 +#define AE_M_MAE 0 /* addr ext pos */ +#define AE_V_MAE 077 /* addr ext mask */ +#define AE_MBZ 0177700 /* CS3 - base + 052/36 - control/status 3 */ -#define CS3_OF 6 -#define CS3_APE 0100000 /* addr perr - NI */ -#define CS3_DPO 0040000 /* data perr odd - NI */ -#define CS3_DPE 0020000 /* data perr even - NI */ -#define CS3_WCO 0010000 /* wchk err odd */ -#define CS3_WCE 0004000 /* wchk err even */ -#define CS3_DBL 0002000 /* dbl word xfer - NI */ -#define CS3_IPCK 0000017 /* wrong par - NI */ -#define CS3_ERR (CS3_APE|CS3_DPO|CS3_DPE|CS3_WCO|CS3_WCE) -#define CS3_MBZ 0001660 -#define CS3_RW (CS1_IE | CS3_IPCK) +#define CS3_OF 6 +#define CS3_APE 0100000 /* addr perr - NI */ +#define CS3_DPO 0040000 /* data perr odd - NI */ +#define CS3_DPE 0020000 /* data perr even - NI */ +#define CS3_WCO 0010000 /* wchk err odd */ +#define CS3_WCE 0004000 /* wchk err even */ +#define CS3_DBL 0002000 /* dbl word xfer - NI */ +#define CS3_IPCK 0000017 /* wrong par - NI */ +#define CS3_ERR (CS3_APE|CS3_DPO|CS3_DPE|CS3_WCO|CS3_WCE) +#define CS3_MBZ 0001660 +#define CS3_RW (CS1_IE | CS3_IPCK) + +#define MBA_OFSMASK 077 /* max 32 reg */ +#define INT 0000 /* int reg flag */ +#define EXT 0100 /* ext reg flag */ -#define MBA_OFSMASK 077 /* max 32 reg */ -#define INT 0000 /* int reg flag */ -#define EXT 0100 /* ext reg flag */ - /* Declarations */ -#define RH11 (cpu_opt & OPT_RH11) +#define RH11 (cpu_opt & OPT_RH11) -struct mbctx { - uint32 cs1; /* ctrl/status 1 */ - uint32 wc; /* word count */ - uint32 ba; /* bus addr */ - uint32 cs2; /* ctrl/status 2 */ - uint32 db; /* data buffer */ - uint32 bae; /* addr ext */ - uint32 cs3; /* ctrl/status 3 */ - uint32 iff; /* int flip flop */ - }; +typedef struct { + uint32 cs1; /* ctrl/status 1 */ + uint32 wc; /* word count */ + uint32 ba; /* bus addr */ + uint32 cs2; /* ctrl/status 2 */ + uint32 db; /* data buffer */ + uint32 bae; /* addr ext */ + uint32 cs3; /* ctrl/status 3 */ + uint32 iff; /* int flip flop */ + } MBACTX; -typedef struct mbctx MBACTX; MBACTX massbus[MBA_NUM]; extern int32 cpu_opt, cpu_bme; extern uint16 *M; extern int32 int_req[IPL_HLVL]; -extern int32 int_vec[IPL_HLVL][32]; extern UNIT cpu_unit; extern FILE *sim_deb; extern FILE *sim_log; @@ -190,91 +190,102 @@ static int32 (*mbabort[MBA_NUM])(void); /* Unibus to register offset map */ -static int32 mba_mapofs[(MBA_OFSMASK + 1) >> 1] = - { INT|0, INT|1, INT|2, EXT|5, INT|3, EXT|1, EXT|2, EXT|4, - EXT|7, INT|4, EXT|3, EXT|6, EXT|8, EXT|9, EXT|10, EXT|11, - EXT|12, EXT|13, EXT|14, EXT|15, EXT|16, EXT|17, EXT|18, EXT|19, - EXT|20, EXT|21, EXT|22, EXT|23, EXT|24, EXT|25, EXT|26, EXT|27 }; - +static int32 mba_mapofs[(MBA_OFSMASK + 1) >> 1] = { + INT|0, INT|1, INT|2, EXT|5, INT|3, EXT|1, EXT|2, EXT|4, + EXT|7, INT|4, EXT|3, EXT|6, EXT|8, EXT|9, EXT|10, EXT|11, + EXT|12, EXT|13, EXT|14, EXT|15, EXT|16, EXT|17, EXT|18, EXT|19, + EXT|20, EXT|21, EXT|22, EXT|23, EXT|24, EXT|25, EXT|26, EXT|27 + }; + /* Massbus adapter data structures - mbax_dev RHx device descriptor - mbax_unit RHx units - mbax_reg RHx register list + mbax_dev RHx device descriptor + mbax_unit RHx units + mbax_reg RHx register list */ -DIB mba0_dib = { IOBA_RP, IOLN_RP, &mba_rd, &mba_wr, - 1, IVCL (RP), VEC_RP, { &mba0_inta } }; +DIB mba0_dib = { + IOBA_RP, IOLN_RP, &mba_rd, &mba_wr, + 1, IVCL (RP), VEC_RP, { &mba0_inta } + }; UNIT mba0_unit = { UDATA (NULL, 0, 0) }; REG mba0_reg[] = { - { ORDATA (CS1, massbus[0].cs1, 16) }, - { ORDATA (WC, massbus[0].wc, 16) }, - { ORDATA (BA, massbus[0].ba, 16) }, - { ORDATA (CS2, massbus[0].cs2, 16) }, - { ORDATA (DB, massbus[0].db, 16) }, - { ORDATA (BAE, massbus[0].bae, 6) }, - { ORDATA (CS3, massbus[0].cs3, 16) }, - { FLDATA (IFF, massbus[0].iff, 0) }, - { FLDATA (INT, IREQ (RP), INT_V_RP) }, - { FLDATA (SC, massbus[0].cs1, CSR_V_ERR) }, - { FLDATA (DONE, massbus[0].cs1, CSR_V_DONE) }, - { FLDATA (IE, massbus[0].cs1, CSR_V_IE) }, - { ORDATA (DEVADDR, mba0_dib.ba, 32), REG_HRO }, - { ORDATA (DEVVEC, mba0_dib.vec, 16), REG_HRO }, - { NULL } }; + { ORDATA (CS1, massbus[0].cs1, 16) }, + { ORDATA (WC, massbus[0].wc, 16) }, + { ORDATA (BA, massbus[0].ba, 16) }, + { ORDATA (CS2, massbus[0].cs2, 16) }, + { ORDATA (DB, massbus[0].db, 16) }, + { ORDATA (BAE, massbus[0].bae, 6) }, + { ORDATA (CS3, massbus[0].cs3, 16) }, + { FLDATA (IFF, massbus[0].iff, 0) }, + { FLDATA (INT, IREQ (RP), INT_V_RP) }, + { FLDATA (SC, massbus[0].cs1, CSR_V_ERR) }, + { FLDATA (DONE, massbus[0].cs1, CSR_V_DONE) }, + { FLDATA (IE, massbus[0].cs1, CSR_V_IE) }, + { ORDATA (DEVADDR, mba0_dib.ba, 32), REG_HRO }, + { ORDATA (DEVVEC, mba0_dib.vec, 16), REG_HRO }, + { NULL } + }; MTAB mba0_mod[] = { - { 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 } }; + { 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 mba0_dev = { - "RHA", &mba0_unit, mba0_reg, mba0_mod, - 1, 0, 0, 0, 0, 0, - NULL, NULL, &mba_reset, - NULL, NULL, NULL, - &mba0_dib, DEV_DEBUG | DEV_DISABLE | DEV_UBUS | DEV_QBUS }; + "RHA", &mba0_unit, mba0_reg, mba0_mod, + 1, 0, 0, 0, 0, 0, + NULL, NULL, &mba_reset, + NULL, NULL, NULL, + &mba0_dib, DEV_DEBUG | DEV_DISABLE | DEV_UBUS | DEV_QBUS + }; -DIB mba1_dib = { IOBA_TU, IOLN_TU, &mba_rd, &mba_wr, - 1, IVCL (TU), VEC_TU, { &mba1_inta } }; +DIB mba1_dib = { + IOBA_TU, IOLN_TU, &mba_rd, &mba_wr, + 1, IVCL (TU), VEC_TU, { &mba1_inta } + }; UNIT mba1_unit = { UDATA (NULL, 0, 0) }; REG mba1_reg[] = { - { ORDATA (CS1, massbus[1].cs1, 16) }, - { ORDATA (WC, massbus[1].wc, 16) }, - { ORDATA (BA, massbus[1].ba, 16) }, - { ORDATA (CS2, massbus[1].cs2, 16) }, - { ORDATA (DB, massbus[1].db, 16) }, - { ORDATA (BAE, massbus[1].bae, 6) }, - { ORDATA (CS3, massbus[1].cs3, 16) }, - { FLDATA (IFF, massbus[1].iff, 0) }, - { FLDATA (INT, IREQ (TU), INT_V_TU) }, - { FLDATA (SC, massbus[1].cs1, CSR_V_ERR) }, - { FLDATA (DONE, massbus[1].cs1, CSR_V_DONE) }, - { FLDATA (IE, massbus[1].cs1, CSR_V_IE) }, - { ORDATA (DEVADDR, mba1_dib.ba, 32), REG_HRO }, - { ORDATA (DEVVEC, mba1_dib.vec, 16), REG_HRO }, - { NULL } }; + { ORDATA (CS1, massbus[1].cs1, 16) }, + { ORDATA (WC, massbus[1].wc, 16) }, + { ORDATA (BA, massbus[1].ba, 16) }, + { ORDATA (CS2, massbus[1].cs2, 16) }, + { ORDATA (DB, massbus[1].db, 16) }, + { ORDATA (BAE, massbus[1].bae, 6) }, + { ORDATA (CS3, massbus[1].cs3, 16) }, + { FLDATA (IFF, massbus[1].iff, 0) }, + { FLDATA (INT, IREQ (TU), INT_V_TU) }, + { FLDATA (SC, massbus[1].cs1, CSR_V_ERR) }, + { FLDATA (DONE, massbus[1].cs1, CSR_V_DONE) }, + { FLDATA (IE, massbus[1].cs1, CSR_V_IE) }, + { ORDATA (DEVADDR, mba1_dib.ba, 32), REG_HRO }, + { ORDATA (DEVVEC, mba1_dib.vec, 16), REG_HRO }, + { NULL } + }; MTAB mba1_mod[] = { - { 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 } }; + { 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 mba1_dev = { - "RHB", &mba1_unit, mba1_reg, mba1_mod, - 1, 0, 0, 0, 0, 0, - NULL, NULL, &mba_reset, - NULL, NULL, NULL, - &mba1_dib, DEV_DEBUG | DEV_DISABLE | DEV_DIS | DEV_UBUS | DEV_QBUS }; - + "RHB", &mba1_unit, mba1_reg, mba1_mod, + 1, 0, 0, 0, 0, 0, + NULL, NULL, &mba_reset, + NULL, NULL, NULL, + &mba1_dib, DEV_DEBUG | DEV_DISABLE | DEV_DIS | DEV_UBUS | DEV_QBUS + }; + /* Read Massbus adapter register */ t_stat mba_rd (int32 *val, int32 pa, int32 mode) @@ -283,51 +294,60 @@ int32 ofs, dat, mb, drv; t_stat r; MBACTX *mbp; -mb = mba_map_pa (pa, &ofs); /* get mb number */ -if ((mb < 0) || (ofs < 0)) return SCPE_NXM; /* valid? */ -mbp = ctxmap[mb]; /* get context */ -drv = GET_UNIT (mbp->cs2); /* get drive */ -mba_upd_cs1 (0, 0, mb); /* update CS1 */ +mb = mba_map_pa (pa, &ofs); /* get mb number */ +if ((mb < 0) || (ofs < 0)) return SCPE_NXM; /* valid? */ +mbp = ctxmap[mb]; /* get context */ +drv = GET_UNIT (mbp->cs2); /* get drive */ +mba_upd_cs1 (0, 0, mb); /* update CS1 */ -if (ofs & EXT) { /* external? */ - if (!mbregR[mb]) return SCPE_NXM; /* device there? */ - r = mbregR[mb] (val, ofs & ~EXT, drv); /* call device */ - if (r == MBE_NXD) mba_set_cs2 (CS2_NED, mb); /* nx drive? */ - else if (r == MBE_NXR) return SCPE_NXM; /* nx reg? */ - return SCPE_OK; - } +if (ofs & EXT) { /* external? */ + if (!mbregR[mb]) return SCPE_NXM; /* device there? */ + r = mbregR[mb] (val, ofs & ~EXT, drv); /* call device */ + if (r == MBE_NXD) mba_set_cs2 (CS2_NED, mb); /* nx drive? */ + else if (r == MBE_NXR) return SCPE_NXM; /* nx reg? */ + return SCPE_OK; + } + +switch (ofs) { /* case on reg */ + + case CS1_OF: /* CS1 */ + if (!mbregR[mb]) return SCPE_NXM; /* nx device? */ + r = mbregR[mb] (&dat, ofs, drv); /* get dev cs1 */ + if (r == MBE_NXD) mba_set_cs2 (CS2_NED, mb); /* nx drive? */ + *val = mbp->cs1 | dat; + break; + + case WC_OF: /* WC */ + *val = mbp->wc; + break; + + case BA_OF: /* BA */ + *val = mbp->ba & ~BA_MBZ; + break; + + case CS2_OF: /* CS2 */ + *val = mbp->cs2 = (mbp->cs2 & ~CS2_MBZ) | CS2_IR | CS2_OR; + break; + + case DB_OF: /* DB */ + *val = mbp->db; + break; + + case BAE_OF: /* BAE */ + *val = mbp->bae = mbp->bae & ~AE_MBZ; + break; + + case CS3_OF: /* CS3 */ + *val = mbp->cs3 = (mbp->cs3 & ~(CS1_IE | CS3_MBZ)) | (mbp->cs1 & CS1_IE); + break; + + default: /* huh? */ + return SCPE_NXM; + } -switch (ofs) { /* case on reg */ -case CS1_OF: /* CS1 */ - if (!mbregR[mb]) return SCPE_NXM; /* nx device? */ - r = mbregR[mb] (&dat, ofs, drv); /* get dev cs1 */ - if (r == MBE_NXD) mba_set_cs2 (CS2_NED, mb); /* nx drive? */ - *val = mbp->cs1 | dat; - break; -case WC_OF: /* WC */ - *val = mbp->wc; - break; -case BA_OF: /* BA */ - *val = mbp->ba & ~BA_MBZ; - break; -case CS2_OF: /* CS2 */ - *val = mbp->cs2 = (mbp->cs2 & ~CS2_MBZ) | CS2_IR | CS2_OR; - break; -case DB_OF: /* DB */ - *val = mbp->db; - break; -case BAE_OF: /* BAE */ - *val = mbp->bae = mbp->bae & ~AE_MBZ; - break; -case CS3_OF: /* CS3 */ - *val = mbp->cs3 = (mbp->cs3 & ~(CS1_IE | CS3_MBZ)) | (mbp->cs1 & CS1_IE); - break; -default: /* huh? */ - return SCPE_NXM; - } return SCPE_OK; } - + t_stat mba_wr (int32 val, int32 pa, int32 access) { int32 ofs, cs1f, drv, mb; @@ -335,108 +355,119 @@ t_stat r; t_bool cs1dt; MBACTX *mbp; -mb = mba_map_pa (pa, &ofs); /* get mb number */ -if ((mb < 0) || (ofs < 0)) return SCPE_NXM; /* valid? */ -mbp = ctxmap[mb]; /* get context */ -drv = GET_UNIT (mbp->cs2); /* get drive */ +mb = mba_map_pa (pa, &ofs); /* get mb number */ +if ((mb < 0) || (ofs < 0)) return SCPE_NXM; /* valid? */ +mbp = ctxmap[mb]; /* get context */ +drv = GET_UNIT (mbp->cs2); /* get drive */ -if (ofs & EXT) { /* external? */ - if (!mbregW[mb]) return SCPE_NXM; /* device there? */ - if ((access == WRITEB) && (pa & 1)) /* byte writes */ - val = val << 8; /* don't work */ - r = mbregW[mb] (val, ofs & ~EXT, drv); /* write dev reg */ - if (r == MBE_NXD) mba_set_cs2 (CS2_NED, mb); /* nx drive? */ - else if (r == MBE_NXR) return SCPE_NXM; /* nx reg? */ - mba_upd_cs1 (0, 0, mb); /* update status */ - return SCPE_OK; - } +if (ofs & EXT) { /* external? */ + if (!mbregW[mb]) return SCPE_NXM; /* device there? */ + if ((access == WRITEB) && (pa & 1)) /* byte writes */ + val = val << 8; /* don't work */ + r = mbregW[mb] (val, ofs & ~EXT, drv); /* write dev reg */ + if (r == MBE_NXD) mba_set_cs2 (CS2_NED, mb); /* nx drive? */ + else if (r == MBE_NXR) return SCPE_NXM; /* nx reg? */ + mba_upd_cs1 (0, 0, mb); /* update status */ + return SCPE_OK; + } -cs1f = 0; /* no int on cs1 upd */ -switch (ofs) { /* case on reg */ -case CS1_OF: /* CS1 */ - if (!mbregW[mb]) return SCPE_NXM; /* device exist? */ - if ((access == WRITEB) && (pa & 1)) val = val << 8; - if (val & CS1_TRE) { /* error clear? */ - mbp->cs1 = mbp->cs1 & ~CS1_TRE; /* clr CS1 */ - mbp->cs2 = mbp->cs2 & ~CS2_ERR; /* clr CS2<15:8> */ - mbp->cs3 = mbp->cs3 & ~CS3_ERR; /* clr CS3<15:11> */ - } - if ((access == WRITE) || (pa & 1)) { /* hi byte write? */ - if (mbp->cs1 & CS1_DONE) /* done set? */ - mbp->cs1 = (mbp->cs1 & ~CS1_UAE) | (val & CS1_UAE); } - if ((access == WRITE) || !(pa & 1)) { /* lo byte write? */ - if ((val & CS1_DONE) && (val & CS1_IE)) /* to DONE+IE? */ - mbp->iff = 1; /* set CSTB INTR */ - mbp->cs1 = (mbp->cs1 & ~CS1_IE) | (val & CS1_IE); - cs1dt = (val & CS1_GO) && (GET_FNC (val) >= FNC_XFER); - if (cs1dt && ((mbp->cs1 & CS1_DONE) == 0)) /* dt, done clr? */ - mba_set_cs2 (CS2_PGE, mb); /* prgm error */ - else { - r = mbregW[mb] (val & 077, ofs, drv); /* write dev CS1 */ - if (r == MBE_NXD) mba_set_cs2 (CS2_NED, mb); /* nx drive? */ - else if (r == MBE_NXR) return SCPE_NXM; /* nx reg? */ - else if (cs1dt && (r == SCPE_OK)) { /* xfer, no err? */ - mbp->cs1 &= ~(CS1_TRE | CS1_MCPE | CS1_DONE); - mbp->cs2 &= ~CS2_ERR; /* clear errors */ - mbp->cs3 &= ~(CS3_ERR | CS3_DBL); - } - } - } - mbp->cs3 = (mbp->cs3 & ~CS1_IE) | /* update CS3 */ - (mbp->cs1 & CS1_IE); - mbp->bae = (mbp->bae & ~CS1_M_UAE) | /* update BAE */ - ((mbp->cs1 >> CS1_V_UAE) & CS1_M_UAE); - break; -case WC_OF: /* WC */ - if (access == WRITEB) val = (pa & 1)? - (mbp->wc & 0377) | (val << 8): (mbp->wc & ~0377) | val; - mbp->wc = val; - break; -case BA_OF: /* BA */ - if (access == WRITEB) val = (pa & 1)? - (mbp->ba & 0377) | (val << 8): (mbp->ba & ~0377) | val; - mbp->ba = val & ~BA_MBZ; - break; -case CS2_OF: /* CS2 */ - if ((access == WRITEB) && (pa & 1)) val = val << 8; - if (val & CS2_CLR) mba_reset (devmap[mb]); /* init? */ - else { - if ((val & ~mbp->cs2) & (CS2_PE | CS2_MXF)) - cs1f = CS1_SC; /* diagn intr */ - if (access == WRITEB) val = (mbp->cs2 & /* merge val */ - ((pa & 1)? 0377: 0177400)) | val; - mbp->cs2 = (mbp->cs2 & ~CS2_RW) | - (val & CS2_RW) | CS2_IR | CS2_OR; } - break; -case DB_OF: /* DB */ - if (access == WRITEB) val = (pa & 1)? - (mbp->db & 0377) | (val << 8): (mbp->db & ~0377) | val; - mbp->db = val; - break; -case BAE_OF: /* BAE */ - if ((access == WRITEB) && (pa & 1)) break; - mbp->bae = val & ~AE_MBZ; - mbp->cs1 = (mbp->cs1 & ~CS1_UAE) | /* update CS1 */ - ((mbp->bae << CS1_V_UAE) & CS1_UAE); - break; -case CS3_OF: /* CS3 */ - if ((access == WRITEB) && (pa & 1)) break; - mbp->cs3 = (mbp->cs3 & ~CS3_RW) | (val & CS3_RW); - mbp->cs1 = (mbp->cs1 & ~CS1_IE) | /* update CS1 */ - (mbp->cs3 & CS1_IE); - break; -default: - return SCPE_NXM; - } -mba_upd_cs1 (cs1f, 0, mb); /* update status */ +cs1f = 0; /* no int on cs1 upd */ +switch (ofs) { /* case on reg */ + + case CS1_OF: /* CS1 */ + if (!mbregW[mb]) return SCPE_NXM; /* device exist? */ + if ((access == WRITEB) && (pa & 1)) val = val << 8; + if (val & CS1_TRE) { /* error clear? */ + mbp->cs1 = mbp->cs1 & ~CS1_TRE; /* clr CS1 */ + mbp->cs2 = mbp->cs2 & ~CS2_ERR; /* clr CS2<15:8> */ + mbp->cs3 = mbp->cs3 & ~CS3_ERR; /* clr CS3<15:11> */ + } + if ((access == WRITE) || (pa & 1)) { /* hi byte write? */ + if (mbp->cs1 & CS1_DONE) /* done set? */ + mbp->cs1 = (mbp->cs1 & ~CS1_UAE) | (val & CS1_UAE); + } + if ((access == WRITE) || !(pa & 1)) { /* lo byte write? */ + if ((val & CS1_DONE) && (val & CS1_IE)) /* to DONE+IE? */ + mbp->iff = 1; /* set CSTB INTR */ + mbp->cs1 = (mbp->cs1 & ~CS1_IE) | (val & CS1_IE); + cs1dt = (val & CS1_GO) && (GET_FNC (val) >= FNC_XFER); + if (cs1dt && ((mbp->cs1 & CS1_DONE) == 0)) /* dt, done clr? */ + mba_set_cs2 (CS2_PGE, mb); /* prgm error */ + else { + r = mbregW[mb] (val & 077, ofs, drv); /* write dev CS1 */ + if (r == MBE_NXD) mba_set_cs2 (CS2_NED, mb); /* nx drive? */ + else if (r == MBE_NXR) return SCPE_NXM; /* nx reg? */ + else if (cs1dt && (r == SCPE_OK)) { /* xfer, no err? */ + mbp->cs1 &= ~(CS1_TRE | CS1_MCPE | CS1_DONE); + mbp->cs2 &= ~CS2_ERR; /* clear errors */ + mbp->cs3 &= ~(CS3_ERR | CS3_DBL); + } + } + } + mbp->cs3 = (mbp->cs3 & ~CS1_IE) | /* update CS3 */ + (mbp->cs1 & CS1_IE); + mbp->bae = (mbp->bae & ~CS1_M_UAE) | /* update BAE */ + ((mbp->cs1 >> CS1_V_UAE) & CS1_M_UAE); + break; + + case WC_OF: /* WC */ + if (access == WRITEB) val = (pa & 1)? + (mbp->wc & 0377) | (val << 8): (mbp->wc & ~0377) | val; + mbp->wc = val; + break; + + case BA_OF: /* BA */ + if (access == WRITEB) val = (pa & 1)? + (mbp->ba & 0377) | (val << 8): (mbp->ba & ~0377) | val; + mbp->ba = val & ~BA_MBZ; + break; + + case CS2_OF: /* CS2 */ + if ((access == WRITEB) && (pa & 1)) val = val << 8; + if (val & CS2_CLR) mba_reset (devmap[mb]); /* init? */ + else { + if ((val & ~mbp->cs2) & (CS2_PE | CS2_MXF)) + cs1f = CS1_SC; /* diagn intr */ + if (access == WRITEB) val = (mbp->cs2 & /* merge val */ + ((pa & 1)? 0377: 0177400)) | val; + mbp->cs2 = (mbp->cs2 & ~CS2_RW) | + (val & CS2_RW) | CS2_IR | CS2_OR; + } + break; + + case DB_OF: /* DB */ + if (access == WRITEB) val = (pa & 1)? + (mbp->db & 0377) | (val << 8): (mbp->db & ~0377) | val; + mbp->db = val; + break; + + case BAE_OF: /* BAE */ + if ((access == WRITEB) && (pa & 1)) break; + mbp->bae = val & ~AE_MBZ; + mbp->cs1 = (mbp->cs1 & ~CS1_UAE) | /* update CS1 */ + ((mbp->bae << CS1_V_UAE) & CS1_UAE); + break; + + case CS3_OF: /* CS3 */ + if ((access == WRITEB) && (pa & 1)) break; + mbp->cs3 = (mbp->cs3 & ~CS3_RW) | (val & CS3_RW); + mbp->cs1 = (mbp->cs1 & ~CS1_IE) | /* update CS1 */ + (mbp->cs3 & CS1_IE); + break; + + default: + return SCPE_NXM; + } + +mba_upd_cs1 (cs1f, 0, mb); /* update status */ return SCPE_OK; } - + /* Massbus I/O routines - mb_rdbufW - fetch word buffer from memory - mb_wrbufW - store word buffer into memory - mb_chbufW - compare word buffer with memory + mb_rdbufW - fetch word buffer from memory + mb_wrbufW - store word buffer into memory + mb_chbufW - compare word buffer with memory Returns number of bytes successfully transferred/checked */ @@ -447,33 +478,34 @@ MBACTX *mbp; int32 i, j, ba, mbc, pbc; uint32 pa; -bc = bc & ~1; /* bc even */ -if (mb >= MBA_NUM) return 0; /* valid MBA? */ -mbp = ctxmap[mb]; /* get context */ -ba = (mbp->bae << 16) | mbp->ba; /* get busaddr */ -mbc = (0200000 - mbp->wc) << 1; /* MB byte count */ -if (bc > mbc) bc = mbc; /* use smaller */ -for (i = 0; i < bc; i = i + pbc) { /* loop by pages */ - if (RH11 && cpu_bme) pa = Map_Addr (ba); /* map addr */ - else pa = ba; - if (!ADDR_IS_MEM (pa)) { /* NXM? */ - mba_set_cs2 (CS2_NEM, mb); /* set error */ - break; } - pbc = UBM_PAGSIZE - UBM_GETOFF (pa); /* left in page */ - if (pbc > (bc - i)) pbc = bc - i; /* limit to rem xfr */ - for (j = 0; j < pbc; j = j + 2) { /* loop by words */ - *buf++ = M[pa >> 1]; /* fetch word */ - if (!(mbp->cs2 & CS2_UAI)) { /* if not inhb */ - ba = ba + 2; /* incr ba, pa */ - pa = pa + 2; - } - } - } -mbp->wc = (mbp->wc + (bc >> 1)) & DMASK; /* update wc */ -mbp->ba = ba & DMASK; /* update ba */ -mbp->bae = (ba >> 16) & ~AE_MBZ; /* upper 6b */ -mbp->cs1 = (mbp->cs1 & ~ CS1_UAE) | /* update CS1 */ - ((mbp->bae << CS1_V_UAE) & CS1_UAE); +bc = bc & ~1; /* bc even */ +if (mb >= MBA_NUM) return 0; /* valid MBA? */ +mbp = ctxmap[mb]; /* get context */ +ba = (mbp->bae << 16) | mbp->ba; /* get busaddr */ +mbc = (0200000 - mbp->wc) << 1; /* MB byte count */ +if (bc > mbc) bc = mbc; /* use smaller */ +for (i = 0; i < bc; i = i + pbc) { /* loop by pages */ + if (RH11 && cpu_bme) pa = Map_Addr (ba); /* map addr */ + else pa = ba; + if (!ADDR_IS_MEM (pa)) { /* NXM? */ + mba_set_cs2 (CS2_NEM, mb); /* set error */ + break; + } + pbc = UBM_PAGSIZE - UBM_GETOFF (pa); /* left in page */ + if (pbc > (bc - i)) pbc = bc - i; /* limit to rem xfr */ + for (j = 0; j < pbc; j = j + 2) { /* loop by words */ + *buf++ = M[pa >> 1]; /* fetch word */ + if (!(mbp->cs2 & CS2_UAI)) { /* if not inhb */ + ba = ba + 2; /* incr ba, pa */ + pa = pa + 2; + } + } + } +mbp->wc = (mbp->wc + (bc >> 1)) & DMASK; /* update wc */ +mbp->ba = ba & DMASK; /* update ba */ +mbp->bae = (ba >> 16) & ~AE_MBZ; /* upper 6b */ +mbp->cs1 = (mbp->cs1 & ~ CS1_UAE) | /* update CS1 */ + ((mbp->bae << CS1_V_UAE) & CS1_UAE); return i; } @@ -483,33 +515,34 @@ MBACTX *mbp; int32 i, j, ba, mbc, pbc; uint32 pa; -bc = bc & ~1; /* bc even */ -if (mb >= MBA_NUM) return 0; /* valid MBA? */ -mbp = ctxmap[mb]; /* get context */ -ba = (mbp->bae << 16) | mbp->ba; /* get busaddr */ -mbc = (0200000 - mbp->wc) << 1; /* MB byte count */ -if (bc > mbc) bc = mbc; /* use smaller */ -for (i = 0; i < bc; i = i + pbc) { /* loop by pages */ - if (RH11 && cpu_bme) pa = Map_Addr (ba); /* map addr */ - else pa = ba; - if (!ADDR_IS_MEM (pa)) { /* NXM? */ - mba_set_cs2 (CS2_NEM, mb); /* set error */ - break; } - pbc = UBM_PAGSIZE - UBM_GETOFF (pa); /* left in page */ - if (pbc > (bc - i)) pbc = bc - i; /* limit to rem xfr */ - for (j = 0; j < pbc; j = j + 2) { /* loop by words */ - M[pa >> 1] = *buf++; /* put word */ - if (!(mbp->cs2 & CS2_UAI)) { /* if not inhb */ - ba = ba + 2; /* incr ba, pa */ - pa = pa + 2; - } - } - } -mbp->wc = (mbp->wc + (bc >> 1)) & DMASK; /* update wc */ -mbp->ba = ba & DMASK; /* update ba */ -mbp->bae = (ba >> 16) & ~AE_MBZ; /* upper 6b */ -mbp->cs1 = (mbp->cs1 & ~ CS1_UAE) | /* update CS1 */ - ((mbp->bae << CS1_V_UAE) & CS1_UAE); +bc = bc & ~1; /* bc even */ +if (mb >= MBA_NUM) return 0; /* valid MBA? */ +mbp = ctxmap[mb]; /* get context */ +ba = (mbp->bae << 16) | mbp->ba; /* get busaddr */ +mbc = (0200000 - mbp->wc) << 1; /* MB byte count */ +if (bc > mbc) bc = mbc; /* use smaller */ +for (i = 0; i < bc; i = i + pbc) { /* loop by pages */ + if (RH11 && cpu_bme) pa = Map_Addr (ba); /* map addr */ + else pa = ba; + if (!ADDR_IS_MEM (pa)) { /* NXM? */ + mba_set_cs2 (CS2_NEM, mb); /* set error */ + break; + } + pbc = UBM_PAGSIZE - UBM_GETOFF (pa); /* left in page */ + if (pbc > (bc - i)) pbc = bc - i; /* limit to rem xfr */ + for (j = 0; j < pbc; j = j + 2) { /* loop by words */ + M[pa >> 1] = *buf++; /* put word */ + if (!(mbp->cs2 & CS2_UAI)) { /* if not inhb */ + ba = ba + 2; /* incr ba, pa */ + pa = pa + 2; + } + } + } +mbp->wc = (mbp->wc + (bc >> 1)) & DMASK; /* update wc */ +mbp->ba = ba & DMASK; /* update ba */ +mbp->bae = (ba >> 16) & ~AE_MBZ; /* upper 6b */ +mbp->cs1 = (mbp->cs1 & ~ CS1_UAE) | /* update CS1 */ + ((mbp->bae << CS1_V_UAE) & CS1_UAE); return i; } @@ -519,41 +552,43 @@ MBACTX *mbp; int32 i, j, ba, mbc, pbc; uint32 pa; -bc = bc & ~1; /* bc even */ -if (mb >= MBA_NUM) return 0; /* valid MBA? */ -mbp = ctxmap[mb]; /* get context */ -ba = (mbp->bae << 16) | mbp->ba; /* get busaddr */ -mbc = (0200000 - mbp->wc) << 1; /* MB byte count */ -if (bc > mbc) bc = mbc; /* use smaller */ -for (i = 0; i < bc; i = i + pbc) { /* loop by pages */ - if (RH11 && cpu_bme) pa = Map_Addr (ba); /* map addr */ - else pa = ba; - if (!ADDR_IS_MEM (pa)) { /* NXM? */ - mba_set_cs2 (CS2_NEM, mb); /* set error */ - break; } - pbc = UBM_PAGSIZE - UBM_GETOFF (pa); /* left in page */ - if (pbc > (bc - i)) pbc = bc - i; /* limit to rem xfr */ - for (j = 0; j < pbc; j = j + 2) { /* loop by words */ - mbp->db = *buf++; /* get dev word */ - if (M[pa >> 1] != mbp->db) { /* miscompare? */ - mba_set_cs2 (CS2_WCE, mb); /* set error */ - mbp->cs3 = mbp->cs3 | /* set even/odd */ - ((pa & 1)? CS3_WCO: CS3_WCE); - break; } - if (!(mbp->cs2 & CS2_UAI)) { /* if not inhb */ - ba = ba + 2; /* incr ba, pa */ - pa = pa + 2; - } - } - } -mbp->wc = (mbp->wc + (bc >> 1)) & DMASK; /* update wc */ -mbp->ba = ba & DMASK; /* update ba */ -mbp->bae = (ba >> 16) & ~AE_MBZ; /* upper 6b */ -mbp->cs1 = (mbp->cs1 & ~ CS1_UAE) | /* update CS1 */ - ((mbp->bae << CS1_V_UAE) & CS1_UAE); +bc = bc & ~1; /* bc even */ +if (mb >= MBA_NUM) return 0; /* valid MBA? */ +mbp = ctxmap[mb]; /* get context */ +ba = (mbp->bae << 16) | mbp->ba; /* get busaddr */ +mbc = (0200000 - mbp->wc) << 1; /* MB byte count */ +if (bc > mbc) bc = mbc; /* use smaller */ +for (i = 0; i < bc; i = i + pbc) { /* loop by pages */ + if (RH11 && cpu_bme) pa = Map_Addr (ba); /* map addr */ + else pa = ba; + if (!ADDR_IS_MEM (pa)) { /* NXM? */ + mba_set_cs2 (CS2_NEM, mb); /* set error */ + break; + } + pbc = UBM_PAGSIZE - UBM_GETOFF (pa); /* left in page */ + if (pbc > (bc - i)) pbc = bc - i; /* limit to rem xfr */ + for (j = 0; j < pbc; j = j + 2) { /* loop by words */ + mbp->db = *buf++; /* get dev word */ + if (M[pa >> 1] != mbp->db) { /* miscompare? */ + mba_set_cs2 (CS2_WCE, mb); /* set error */ + mbp->cs3 = mbp->cs3 | /* set even/odd */ + ((pa & 1)? CS3_WCO: CS3_WCE); + break; + } + if (!(mbp->cs2 & CS2_UAI)) { /* if not inhb */ + ba = ba + 2; /* incr ba, pa */ + pa = pa + 2; + } + } + } +mbp->wc = (mbp->wc + (bc >> 1)) & DMASK; /* update wc */ +mbp->ba = ba & DMASK; /* update ba */ +mbp->bae = (ba >> 16) & ~AE_MBZ; /* upper 6b */ +mbp->cs1 = (mbp->cs1 & ~ CS1_UAE) | /* update CS1 */ + ((mbp->bae << CS1_V_UAE) & CS1_UAE); return i; } - + /* Device access, status, and interrupt routines */ void mba_set_don (uint32 mb) @@ -625,13 +660,16 @@ MBACTX *mbp; if (mb >= MBA_NUM) return; mbp = ctxmap[mb]; -if ((set & ~mbp->cs1) & CS1_DONE) /* DONE 0 to 1? */ - mbp->iff = (mbp->cs1 & CS1_IE)? 1: 0; /* CSTB INTR <- IE */ +if ((set & ~mbp->cs1) & CS1_DONE) /* DONE 0 to 1? */ + mbp->iff = (mbp->cs1 & CS1_IE)? 1: 0; /* CSTB INTR <- IE */ mbp->cs1 = (mbp->cs1 & ~(clr | CS1_MCPE | CS1_MBZ | CS1_DRV)) | CS1_DVA | set; if (mbp->cs2 & CS2_ERR) mbp->cs1 = mbp->cs1 | CS1_TRE | CS1_SC; else if (mbp->cs1 & CS1_TRE) mbp->cs1 = mbp->cs1 | CS1_SC; -if (mbp->iff || ((mbp->cs1 & CS1_SC) && (mbp->cs1 & CS1_DONE) && (mbp->cs1 & CS1_IE))) - mba_set_int (mb); +if (mbp->iff || + ((mbp->cs1 & CS1_SC) && + (mbp->cs1 & CS1_DONE) && + (mbp->cs1 & CS1_IE))) + mba_set_int (mb); else mba_clr_int (mb); return; } @@ -651,18 +689,18 @@ return; int32 mba0_inta (void) { -massbus[0].cs1 &= ~CS1_IE; /* clear int enable */ -massbus[0].cs3 &= ~CS1_IE; /* in both registers */ -massbus[0].iff = 0; /* clear CSTB INTR */ -return mba0_dib.vec; /* acknowledge */ +massbus[0].cs1 &= ~CS1_IE; /* clear int enable */ +massbus[0].cs3 &= ~CS1_IE; /* in both registers */ +massbus[0].iff = 0; /* clear CSTB INTR */ +return mba0_dib.vec; /* acknowledge */ } int32 mba1_inta (void) { -massbus[1].cs1 &= ~CS1_IE; /* clear int enable */ -massbus[1].cs3 &= ~CS1_IE; /* in both registers */ -massbus[1].iff = 0; /* clear CSTB INTR */ -return mba1_dib.vec; /* acknowledge */ +massbus[1].cs1 &= ~CS1_IE; /* clear int enable */ +massbus[1].cs3 &= ~CS1_IE; /* in both registers */ +massbus[1].iff = 0; /* clear CSTB INTR */ +return mba1_dib.vec; /* acknowledge */ } /* Map physical address to Massbus number, offset */ @@ -673,29 +711,29 @@ int32 i, uo, ba, lnt; DEVICE *dptr; DIB *dibp; -for (i = 0; i < MBA_NUM; i++) { /* loop thru ctrls */ - dptr = devmap[i]; /* get device */ - dibp = (DIB *) dptr->ctxt; /* get DIB */ - ba = dibp->ba; - lnt = dibp->lnt; - if ((pa >= ba) && /* in range? */ - (pa < (ba + lnt))) { - if (pa < (ba + (lnt - 4))) { /* not last two? */ - uo = ((pa - ba) & MBA_OFSMASK) >> 1; /* get Unibus offset */ - *ofs = mba_mapofs[uo]; /* map thru PROM */ - return i; /* return ctrl idx */ - } - else if (RH11) return -1; /* RH11? done */ - else { /* RH70 */ - uo = (pa - (ba + (lnt - 4))) >> 1; /* offset relative */ - *ofs = BAE_OF + uo; /* to BAE */ - return i; - } - } - } +for (i = 0; i < MBA_NUM; i++) { /* loop thru ctrls */ + dptr = devmap[i]; /* get device */ + dibp = (DIB *) dptr->ctxt; /* get DIB */ + ba = dibp->ba; + lnt = dibp->lnt; + if ((pa >= ba) && /* in range? */ + (pa < (ba + lnt))) { + if (pa < (ba + (lnt - 4))) { /* not last two? */ + uo = ((pa - ba) & MBA_OFSMASK) >> 1; /* get Unibus offset */ + *ofs = mba_mapofs[uo]; /* map thru PROM */ + return i; /* return ctrl idx */ + } + else if (RH11) return -1; /* RH11? done */ + else { /* RH70 */ + uo = (pa - (ba + (lnt - 4))) >> 1; /* offset relative */ + *ofs = BAE_OF + uo; /* to BAE */ + return i; + } + } + } return -1; } - + /* Reset Massbus adapter */ t_stat mba_reset (DEVICE *dptr) @@ -704,9 +742,9 @@ int32 mb; MBACTX *mbp; for (mb = 0; mb < MBA_NUM; mb++) { - mbp = ctxmap[mb]; - if (dptr == devmap[mb]) break; - } + mbp = ctxmap[mb]; + if (dptr == devmap[mb]) break; + } if (mb >= MBA_NUM) return SCPE_NOFNC; mbp->cs1 = CS1_DONE; mbp->wc = 0; @@ -742,10 +780,10 @@ void init_mbus_tab (void) uint32 i; for (i = 0; i < MBA_NUM; i++) { - mbregR[i] = NULL; - mbregW[i] = NULL; - mbabort[i] = NULL; - } + mbregR[i] = NULL; + mbregW[i] = NULL; + mbabort[i] = NULL; + } return; } @@ -755,25 +793,25 @@ t_stat build_mbus_tab (DEVICE *dptr, DIB *dibp) { uint32 idx; -if ((dptr == NULL) || (dibp == NULL)) return SCPE_IERR; /* validate args */ -idx = dibp->ba; /* Mbus # */ +if ((dptr == NULL) || (dibp == NULL)) return SCPE_IERR; /* validate args */ +idx = dibp->ba; /* Mbus # */ if (idx >= MBA_NUM) return SCPE_STOP; -if ((mbregR[idx] && dibp->rd && /* conflict? */ +if ((mbregR[idx] && dibp->rd && /* conflict? */ (mbregR[idx] != dibp->rd)) || (mbregW[idx] && dibp->wr && (mbregW[idx] != dibp->wr)) || (mbabort[idx] && dibp->ack[0] && (mbabort[idx] != dibp->ack[0]))) { - printf ("Massbus %s assignment conflict at %d\n", - sim_dname (dptr), dibp->ba); - if (sim_log) fprintf (sim_log, - "Massbus %s assignment conflict at %d\n", - sim_dname (dptr), dibp->ba); - return SCPE_STOP; - } -if (dibp->rd) mbregR[idx] = dibp->rd; /* set rd dispatch */ -if (dibp->wr) mbregW[idx] = dibp->wr; /* set wr dispatch */ -if (dibp->ack[0]) mbabort[idx] = dibp->ack[0]; /* set abort dispatch */ + printf ("Massbus %s assignment conflict at %d\n", + sim_dname (dptr), dibp->ba); + if (sim_log) fprintf (sim_log, + "Massbus %s assignment conflict at %d\n", + sim_dname (dptr), dibp->ba); + return SCPE_STOP; + } +if (dibp->rd) mbregR[idx] = dibp->rd; /* set rd dispatch */ +if (dibp->wr) mbregW[idx] = dibp->wr; /* set wr dispatch */ +if (dibp->ack[0]) mbabort[idx] = dibp->ack[0]; /* set abort dispatch */ return SCPE_OK; } diff --git a/PDP11/pdp11_rk.c b/PDP11/pdp11_rk.c index 15002df4..194da02e 100644 --- a/PDP11/pdp11_rk.c +++ b/PDP11/pdp11_rk.c @@ -1,6 +1,6 @@ /* pdp11_rk.c: RK11/RKV11 cartridge disk simulator - Copyright (c) 1993-2004, Robert M Supnik + Copyright (c) 1993-2005, 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"), @@ -19,29 +19,31 @@ 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 + 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/RKV11/RK05 cartridge disk + rk RK11/RKV11/RK05 cartridge disk - 30-Sep-04 RMS Revised Unibus interface - 24-Jan-04 RMS Added increment inhibit, overrun detection, formatting - 29-Dec-03 RMS Added RKV11 support - 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 + 16-Aug-05 RMS Fixed C++ declaration and cast problems + 07-Jul-05 RMS Removed extraneous externs + 30-Sep-04 RMS Revised Unibus interface + 24-Jan-04 RMS Added increment inhibit, overrun detection, formatting + 29-Dec-03 RMS Added RKV11 support + 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 @@ -61,134 +63,133 @@ 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_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 */ +#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 */ +#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 */ +#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 +#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 */ +#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) +#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)) +#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 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 */ +extern uint16 *M; /* memory */ +extern int32 int_req[IPL_HLVL]; + +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); @@ -203,161 +204,185 @@ 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 + 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 } }; +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) } }; + { 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 } }; + { 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 } }; + { 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 | DEV_Q18 }; - + "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 | DEV_Q18 + }; + /* 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 + 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 */ +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 */ +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) @@ -365,60 +390,72 @@ 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; } +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_FMT) && /* format and */ - (func != RKCS_READ) && (func != RKCS_WRITE)) { /* not read or write? */ + rk_set_done (RKER_DRE); /* not att or busy */ + return; + } +if ((rkcs & RKCS_FMT) && /* format and */ + (func != RKCS_READ) && (func != RKCS_WRITE)) { /* not read or write? */ rk_set_done (RKER_PGE); - return; } + 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 */ + 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 */ +uptr->FUNC = func; /* save func */ +uptr->CYL = cyl; /* put on cylinder */ return; } - + /* Service unit timeout If seek in progress, complete seek command @@ -435,156 +472,176 @@ int32 da, cyl, 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; } +drv = (int32) (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); } -sect = GET_SECT (rkda); /* get sector, cyl */ +if ((uptr->flags & UNIT_ATT) == 0) { /* attached? */ + rk_set_done (RKER_DRE); + return IORETURN (rk_stopioe, SCPE_UNATT); + } +sect = GET_SECT (rkda); /* get sector, cyl */ cyl = GET_CYL (rkda); -if (sect >= RK_NUMSC) { /* bad sector? */ - rk_set_done (RKER_NXS); - return SCPE_OK; } -if (cyl >= RK_NUMCY) { /* bad cyl? */ - rk_set_done (RKER_NXC); - return SCPE_OK; } -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 */ -if ((da + wc) > (int32) uptr->capac) { /* overrun? */ - wc = uptr->capac - da; /* trim transfer */ - rker = rker | RKER_OVR; } /* set overrun err */ +if (sect >= RK_NUMSC) { /* bad sector? */ + rk_set_done (RKER_NXS); + return SCPE_OK; + } +if (cyl >= RK_NUMCY) { /* bad cyl? */ + rk_set_done (RKER_NXC); + return SCPE_OK; + } +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 */ +if ((da + wc) > (int32) uptr->capac) { /* overrun? */ + wc = uptr->capac - da; /* trim transfer */ + rker = rker | RKER_OVR; /* set overrun err */ + } err = fseek (uptr->fileref, da * sizeof (int16), SEEK_SET); -if (wc && (err == 0)) { /* seek ok? */ - switch (uptr->FUNC) { /* case on function */ +if (wc && (err == 0)) { /* seek ok? */ + switch (uptr->FUNC) { /* case on function */ - case RKCS_READ: /* read */ - if (rkcs & RKCS_FMT) { /* format? */ - for (i = 0, cda = da; i < wc; i++) { /* fill buffer with cyl #s */ - if (cda >= (int32) uptr->capac) { /* overrun? */ - rker = rker | RKER_OVR; /* set overrun err */ - wc = i; /* trim transfer */ - break; } - rkxb[i] = (cda / RK_NUMWD) / (RK_NUMSF * RK_NUMSC); - cda = cda + RK_NUMWD; /* next sector */ - } /* end for wc */ - } /* end if format */ - else { /* normal read */ - i = fxread (rkxb, sizeof (int16), wc, uptr->fileref); - err = ferror (uptr->fileref); /* read file */ - for ( ; i < wc; i++) rkxb[i] = 0; /* fill buf */ - } - if (rkcs & RKCS_INH) { /* incr inhibit? */ - if (t = Map_WriteW (ma, 2, &rkxb[wc - 1])) { /* store last */ - rker = rker | RKER_NXM; /* NXM? set flag */ - wc = 0; } /* no transfer */ - } - else { /* normal store */ - if (t = Map_WriteW (ma, wc << 1, rkxb)) { /* store buf */ - rker = rker | RKER_NXM; /* NXM? set flag */ - wc = wc - t; } /* adj wd cnt */ - } - break; /* end read */ + case RKCS_READ: /* read */ + if (rkcs & RKCS_FMT) { /* format? */ + for (i = 0, cda = da; i < wc; i++) { /* fill buffer with cyl #s */ + if (cda >= (int32) uptr->capac) { /* overrun? */ + rker = rker | RKER_OVR; /* set overrun err */ + wc = i; /* trim transfer */ + break; + } + rkxb[i] = (cda / RK_NUMWD) / (RK_NUMSF * RK_NUMSC); + cda = cda + RK_NUMWD; /* next sector */ + } /* end for wc */ + } /* end if format */ + else { /* normal read */ + i = fxread (rkxb, sizeof (int16), wc, uptr->fileref); + err = ferror (uptr->fileref); /* read file */ + for ( ; i < wc; i++) rkxb[i] = 0; /* fill buf */ + } + if (rkcs & RKCS_INH) { /* incr inhibit? */ + if (t = Map_WriteW (ma, 2, &rkxb[wc - 1])) { /* store last */ + rker = rker | RKER_NXM; /* NXM? set flag */ + wc = 0; /* no transfer */ + } + } + else { /* normal store */ + if (t = Map_WriteW (ma, wc << 1, rkxb)) { /* store buf */ + rker = rker | RKER_NXM; /* NXM? set flag */ + wc = wc - t; /* adj wd cnt */ + } + } + break; /* end read */ - case RKCS_WRITE: /* write */ - if (rkcs & RKCS_INH) { /* incr inhibit? */ - if (t = Map_ReadW (ma, 2, &comp)) { /* get 1st word */ - rker = rker | RKER_NXM; /* NXM? set flag */ - wc = 0; } /* no transfer */ - for (i = 0; i < wc; i++) rkxb[i] = comp; /* all words same */ - } - else { /* normal fetch */ - if (t = Map_ReadW (ma, wc << 1, rkxb)) { /* 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); - } - break; /* end write */ + case RKCS_WRITE: /* write */ + if (rkcs & RKCS_INH) { /* incr inhibit? */ + if (t = Map_ReadW (ma, 2, &comp)) { /* get 1st word */ + rker = rker | RKER_NXM; /* NXM? set flag */ + wc = 0; /* no transfer */ + } + for (i = 0; i < wc; i++) rkxb[i] = comp; /* all words same */ + } + else { /* normal fetch */ + if (t = Map_ReadW (ma, wc << 1, rkxb)) { /* 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); + } + break; /* end write */ - case RKCS_WCHK: /* write check */ - i = fxread (rkxb, sizeof (int16), wc, uptr->fileref); - if (err = ferror (uptr->fileref)) { /* read error? */ - wc = 0; /* no transfer */ - break; } - for ( ; i < wc; i++) rkxb[i] = 0; /* fill buf */ - awc = wc; /* save wc */ - for (wc = 0, cma = ma; wc < awc; wc++) { /* loop thru buf */ - if (Map_ReadW (cma, 2, &comp)) { /* 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; } - if (!(rkcs & RKCS_INH)) cma = cma + 2; /* next mem addr */ - } /* end for */ - break; /* end wcheck */ + case RKCS_WCHK: /* write check */ + i = fxread (rkxb, sizeof (int16), wc, uptr->fileref); + if (err = ferror (uptr->fileref)) { /* read error? */ + wc = 0; /* no transfer */ + break; + } + for ( ; i < wc; i++) rkxb[i] = 0; /* fill buf */ + awc = wc; /* save wc */ + for (wc = 0, cma = ma; wc < awc; wc++) { /* loop thru buf */ + if (Map_ReadW (cma, 2, &comp)) { /* 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; + } + if (!(rkcs & RKCS_INH)) cma = cma + 2; /* next mem addr */ + } /* end for */ + break; /* end wcheck */ - default: /* read check */ - break; - } /* end switch */ - } /* end else */ + default: /* read check */ + break; + } /* end switch */ + } /* end else */ -rkwc = (rkwc + wc) & 0177777; /* final word count */ -if (!(rkcs & RKCS_INH)) ma = ma + (wc << 1); /* final byte addr */ -rkba = ma & RKBA_IMP; /* lower 16b */ +rkwc = (rkwc + wc) & 0177777; /* final word count */ +if (!(rkcs & RKCS_INH)) ma = ma + (wc << 1); /* final byte addr */ +rkba = ma & RKBA_IMP; /* lower 16b */ rkcs = (rkcs & ~RKCS_MEX) | ((ma >> (16 - RKCS_V_MEX)) & RKCS_MEX); -if ((uptr->FUNC == RKCS_READ) && (rkcs & RKCS_FMT)) /* read format? */ - da = da + (wc * RK_NUMWD); /* count by sectors */ -else da = da + wc + (RK_NUMWD - 1); /* count by words */ +if ((uptr->FUNC == RKCS_READ) && (rkcs & RKCS_FMT)) /* read format? */ + da = da + (wc * RK_NUMWD); /* count by sectors */ +else da = da + wc + (RK_NUMWD - 1); /* count by words */ 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; } +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 + 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 */ +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); } + 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 */ +rkcs = rkcs & ~CSR_DONE; /* clear done */ +rkintq = rkintq & ~RK_CTLI; /* clear ctl int */ +CLR_INT (RK); /* clear int req */ return; } @@ -592,17 +649,19 @@ 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 */ +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) @@ -615,48 +674,49 @@ 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 (uint16)); + uptr = rk_dev.units + i; + sim_cancel (uptr); + uptr->CYL = uptr->FUNC = 0; + uptr->flags = uptr->flags & ~UNIT_SWLK; + } +if (rkxb == NULL) rkxb = (uint16 *) calloc (RK_MAXFR, sizeof (uint16)); 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)) +#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 */ -}; + 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) { diff --git a/PDP11/pdp11_rl.c b/PDP11/pdp11_rl.c index 5a39aa4c..d96a90ff 100644 --- a/PDP11/pdp11_rl.c +++ b/PDP11/pdp11_rl.c @@ -1,6 +1,6 @@ /* pdp11_rl.c: RL11 (RLV12) cartridge disk simulator - Copyright (c) 1993-2004, Robert M Supnik + Copyright (c) 1993-2005, 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"), @@ -19,36 +19,38 @@ 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 + 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 + rl RL11(RLV12)/RL01/RL02 cartridge disk - 30-Sep-04 RMS Revised Unibus interface - 04-Jan-04 RMS Changed sim_fsize calling sequence - 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 + 16-Aug-05 RMS Fixed C++ declaration and cast problems + 07-Jul-05 RMS Removed extraneous externs + 30-Sep-04 RMS Revised Unibus interface + 04-Jan-04 RMS Changed sim_fsize calling sequence + 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 @@ -69,137 +71,136 @@ - VAX Q22 systems - the RL11 must go through the I/O map */ -#if defined (VM_PDP10) /* PDP10 version */ +#if defined (VM_PDP10) /* PDP10 version */ #error "RL11 is not supported on the PDP-10!" -#elif defined (VM_VAX) /* VAX version */ +#elif defined (VM_VAX) /* VAX version */ #include "vax_defs.h" -#else /* PDP-11 version */ +#else /* PDP-11 version */ #include "pdp11_defs.h" extern int32 cpu_opt; #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 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 */ +#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 */ +#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 */ +#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 */ +#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_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) +#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_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)) +#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 */ +#define RLBA_IMP 0177776 /* implemented */ /* RLBAE */ -#define RLBAE_IMP 0000077 /* implemented */ - -extern int32 int_req[IPL_HLVL]; -extern int32 int_vec[IPL_HLVL][32]; +#define RLBAE_IMP 0000077 /* implemented */ -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 */ +extern int32 int_req[IPL_HLVL]; + +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); @@ -215,184 +216,206 @@ 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 + 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 } }; +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) } }; + { 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 } }; + { 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 } }; + { 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 + "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 + }; - 17774400 RLCS read/write - 17774402 RLBA read/write - 17774404 RLDA read/write - 17774406 RLMP read/write - 17774410 RLBAE read/write +/* I/O dispatch routines, 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 */ +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 */ +switch ((PA >> 1) & 07) { /* decode PA<2:1> */ - 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; } + 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 */ - 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 @@ -409,109 +432,120 @@ 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; } +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 ((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; } + 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_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_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 */ + || (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? */ +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)) { /* store buffer */ - rlcs = rlcs | RLCS_ERR | RLCS_NXM; /* nxm */ - wc = wc - t; } /* adjust wc */ - } /* end read */ +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)) { /* 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)) { /* 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_WRITE) && (err == 0)) { /* write? */ + if (t = Map_ReadW (ma, wc << 1, rlxb)) { /* 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)) { /* 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 */ +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)) { /* 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 */ +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; } +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; +rlcs = rlcs | status | CSR_DONE; /* set done */ +if (rlcs & CSR_IE) SET_INT (RL); +else CLR_INT (RL); +return; } /* Device reset @@ -528,10 +562,11 @@ 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 (uint16)); + uptr = rl_dev.units + i; + sim_cancel (uptr); + uptr->STAT = 0; + } +if (rlxb == NULL) rlxb = (uint16 *) calloc (RL_MAXFR, sizeof (uint16)); if (rlxb == NULL) return SCPE_MEM; return SCPE_OK; } @@ -544,19 +579,23 @@ 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 ((p = sim_fsize (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? */ +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 ((p = sim_fsize (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; } + uptr->flags = uptr->flags | UNIT_RL02; + uptr->capac = RL02_SIZE; + } +else { + uptr->flags = uptr->flags & ~UNIT_RL02; + uptr->capac = RL01_SIZE; + } return SCPE_OK; } @@ -575,58 +614,58 @@ 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)) +#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 */ -}; + 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) { diff --git a/PDP11/pdp11_rp.c b/PDP11/pdp11_rp.c index 8e2d8553..f84f7252 100644 --- a/PDP11/pdp11_rp.c +++ b/PDP11/pdp11_rp.c @@ -19,42 +19,43 @@ 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 + 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 + rp RH/RP/RM moving head disks - 18-Mar-05 RMS Added attached test to detach routine - 12-Sep-04 RMS Cloned from pdp11_rp.c + 16-Aug-05 RMS Fixed C++ declaration and cast problems + 18-Mar-05 RMS Added attached test to detach routine + 12-Sep-04 RMS Cloned from pdp11_rp.c Note: The VMS driver and the RP controller documentation state that - ER2 = offset 8 - SN = offset 12 + ER2 = offset 8 + SN = offset 12 But the TOPS-10 and TOPS-20 drivers, and the RP schematics state that - SN = offset 8 - ER2 = offset 12 + SN = offset 8 + ER2 = offset 12 The simulation follows the schematics. The VMS drivers defines but does not use these offsets, and the error logger follows the schematics. */ - + #if defined (VM_PDP10) #error "PDP-10 uses pdp10_rp.c!" #elif defined (VM_PDP11) #include "pdp11_defs.h" -#define INIT_DTYPE RM03_DTYPE -#define INIT_SIZE RM03_SIZE +#define INIT_DTYPE RM03_DTYPE +#define INIT_SIZE RM03_SIZE #elif defined (VM_VAX) #include "vax_defs.h" -#define INIT_DTYPE RP06_DTYPE -#define INIT_SIZE RP06_SIZE -#define DMASK 0xFFFF +#define INIT_DTYPE RP06_DTYPE +#define INIT_SIZE RP06_SIZE +#define DMASK 0xFFFF #if (!UNIBUS) #error "Qbus not supported!" #endif @@ -63,197 +64,197 @@ #include -#define RP_CTRL 0 /* ctrl is RP */ -#define RM_CTRL 1 /* ctrl is RM */ -#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))) -#define RM_OF (MBA_RMASK + 1) +#define RP_CTRL 0 /* ctrl is RP */ +#define RM_CTRL 1 /* ctrl is RM */ +#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))) +#define RM_OF (MBA_RMASK + 1) /* 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 */ +#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 CYL u3 /* current cylinder */ /* RPCS1, RMCS1 - control/status 1 - offset 0 */ -#define RP_CS1_OF 0 -#define RM_CS1_OF (0 + RM_OF) -#define CS1_GO CSR_GO /* go */ -#define CS1_V_FNC 1 /* function pos */ -#define CS1_M_FNC 037 /* function mask */ -#define CS1_N_FNC (CS1_M_FNC + 1) -#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_RW 076 -#define GET_FNC(x) (((x) >> CS1_V_FNC) & CS1_M_FNC) +#define RP_CS1_OF 0 +#define RM_CS1_OF (0 + RM_OF) +#define CS1_GO CSR_GO /* go */ +#define CS1_V_FNC 1 /* function pos */ +#define CS1_M_FNC 037 /* function mask */ +#define CS1_N_FNC (CS1_M_FNC + 1) +#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_RW 076 +#define GET_FNC(x) (((x) >> CS1_V_FNC) & CS1_M_FNC) /* RPDS, RMDS - drive status - offset 1 */ -#define RP_DS_OF 1 -#define RM_DS_OF (1 + RM_OF) -#define DS_OFM 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 +#define RP_DS_OF 1 +#define RM_DS_OF (1 + RM_OF) +#define DS_OFM 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, RMER1 - error status 1 - offset 2 */ -#define RP_ER1_OF 2 -#define RM_ER1_OF (2 + RM_OF) -#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 */ +#define RP_ER1_OF 2 +#define RM_ER1_OF (2 + RM_OF) +#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 */ /* RPMR, RMMR - maintenace register - offset 3*/ -#define RP_MR_OF 3 -#define RM_MR_OF (3 + RM_OF) +#define RP_MR_OF 3 +#define RM_MR_OF (3 + RM_OF) /* RPAS, RMAS - attention summary - offset 4 */ -#define RP_AS_OF 4 -#define RM_AS_OF (4 + RM_OF) -#define AS_U0 0000001 /* unit 0 flag */ +#define RP_AS_OF 4 +#define RM_AS_OF (4 + RM_OF) +#define AS_U0 0000001 /* unit 0 flag */ /* RPDA, RMDA - sector/track - offset 5 */ -#define RP_DA_OF 5 -#define RM_DA_OF (5 + RM_OF) -#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) +#define RP_DA_OF 5 +#define RM_DA_OF (5 + RM_OF) +#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) /* RPDT, RMDT - drive type - offset 6 */ -#define RP_DT_OF 6 -#define RM_DT_OF (6 + RM_OF) +#define RP_DT_OF 6 +#define RM_DT_OF (6 + RM_OF) /* RPLA, RMLA - look ahead register - offset 7 */ -#define RP_LA_OF 7 -#define RM_LA_OF (7 + RM_OF) -#define LA_V_SC 6 /* sector pos */ +#define RP_LA_OF 7 +#define RM_LA_OF (7 + RM_OF) +#define LA_V_SC 6 /* sector pos */ /* RPSN, RMSN - serial number - offset 8 */ -#define RP_SN_OF 8 -#define RM_SN_OF (8 + RM_OF) +#define RP_SN_OF 8 +#define RM_SN_OF (8 + RM_OF) /* RPOF, RMOF - offset register - offset 9 */ -#define RP_OF_OF 9 -#define RM_OF_OF (9 + RM_OF) -#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 +#define RP_OF_OF 9 +#define RM_OF_OF (9 + RM_OF) +#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, RMDC - desired cylinder - offset 10 */ -#define RP_DC_OF 10 -#define RM_DC_OF (10 + RM_OF) -#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)) +#define RP_DC_OF 10 +#define RM_DC_OF (10 + RM_OF) +#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 - current cylinder - offset 11 RMHR - holding register - offset 11 */ -#define RP_CC_OF 11 -#define RM_HR_OF (11 + RM_OF) +#define RP_CC_OF 11 +#define RM_HR_OF (11 + RM_OF) /* RPER2 - error status 2 - drive unsafe conditions - unimplemented - offset 12 RMMR2 - maintenance register - unimplemented - offset 12 */ -#define RP_ER2_OF 12 -#define RM_MR2_OF (12 + RM_OF) +#define RP_ER2_OF 12 +#define RM_MR2_OF (12 + RM_OF) /* RPER3 - error status 3 - more unsafe conditions - unimplemented - offset 13 RMER2 - error status 2 - unimplemented - offset 13 */ -#define RP_ER3_OF 13 -#define RM_ER2_OF (13 + RM_OF) +#define RP_ER3_OF 13 +#define RM_ER2_OF (13 + RM_OF) /* RPEC1, RMEC1 - ECC status 1 - unimplemented - offset 14 */ -#define RP_EC1_OF 14 -#define RM_EC1_OF (14 + RM_OF) +#define RP_EC1_OF 14 +#define RM_EC1_OF (14 + RM_OF) /* RPEC2, RMEC1 - ECC status 2 - unimplemented - offset 15 */ -#define RP_EC2_OF 15 -#define RM_EC2_OF (15 + RM_OF) - +#define RP_EC2_OF 15 +#define RM_EC2_OF (15 + RM_OF) + /* This controller supports many different disk drive types: - type #sectors/ #surfaces/ #cylinders/ - surface cylinder drive + 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 + 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 @@ -262,91 +263,93 @@ Note: the RP07, despite its designation, belongs to the RM family */ -#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 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 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 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 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 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) +#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) -#define RP_CTRL 0 -#define RM_CTRL 1 +#define RP_CTRL 0 +#define RM_CTRL 1 struct drvtyp { - int32 sect; /* sectors */ - int32 surf; /* surfaces */ - int32 cyl; /* cylinders */ - int32 size; /* #blocks */ - int32 devtype; /* device type */ - int32 ctrl; /* ctrl type */ -}; + int32 sect; /* sectors */ + int32 surf; /* surfaces */ + int32 cyl; /* cylinders */ + int32 size; /* #blocks */ + int32 devtype; /* device type */ + int32 ctrl; /* ctrl type */ + }; static struct drvtyp drv_tab[] = { - { RM03_SECT, RM03_SURF, RM03_CYL, RM03_SIZE, RM03_DEV, RM_CTRL }, - { RP04_SECT, RP04_SURF, RP04_CYL, RP04_SIZE, RP04_DEV, RP_CTRL }, - { RM80_SECT, RM80_SURF, RM80_CYL, RM80_SIZE, RM80_DEV, RM_CTRL }, - { RP06_SECT, RP06_SURF, RP06_CYL, RP06_SIZE, RP06_DEV, RP_CTRL }, - { RM05_SECT, RM05_SURF, RM05_CYL, RM05_SIZE, RM05_DEV, RM_CTRL }, - { RP07_SECT, RP07_SURF, RP07_CYL, RP07_SIZE, RP07_DEV, RM_CTRL }, - { 0 } }; - -uint16 *rpxb = NULL; /* xfer buffer */ -uint16 rpcs1[RP_NUMDR] = { 0 }; /* control/status 1 */ -uint16 rpda[RP_NUMDR] = { 0 }; /* track/sector */ -uint16 rpds[RP_NUMDR] = { 0 }; /* drive status */ -uint16 rper1[RP_NUMDR] = { 0 }; /* error status 1 */ -uint16 rmhr[RP_NUMDR] = { 0 }; /* holding reg */ -uint16 rpmr[RP_NUMDR] = { 0 }; /* maint reg */ -uint16 rmmr2[RP_NUMDR] = { 0 }; /* maint reg 2 */ -uint16 rpof[RP_NUMDR] = { 0 }; /* offset */ -uint16 rpdc[RP_NUMDR] = { 0 }; /* cylinder */ -uint16 rper2[RP_NUMDR] = { 0 }; /* error status 2 */ -uint16 rper3[RP_NUMDR] = { 0 }; /* error status 3 */ -uint16 rpec1[RP_NUMDR] = { 0 }; /* ECC correction 1 */ -uint16 rpec2[RP_NUMDR] = { 0 }; /* ECC correction 2 */ -int32 rp_stopioe = 1; /* stop on error */ -int32 rp_swait = 10; /* seek time */ -int32 rp_rwait = 10; /* rotate time */ + { RM03_SECT, RM03_SURF, RM03_CYL, RM03_SIZE, RM03_DEV, RM_CTRL }, + { RP04_SECT, RP04_SURF, RP04_CYL, RP04_SIZE, RP04_DEV, RP_CTRL }, + { RM80_SECT, RM80_SURF, RM80_CYL, RM80_SIZE, RM80_DEV, RM_CTRL }, + { RP06_SECT, RP06_SURF, RP06_CYL, RP06_SIZE, RP06_DEV, RP_CTRL }, + { RM05_SECT, RM05_SURF, RM05_CYL, RM05_SIZE, RM05_DEV, RM_CTRL }, + { RP07_SECT, RP07_SURF, RP07_CYL, RP07_SIZE, RP07_DEV, RM_CTRL }, + { 0 } + }; + +uint16 *rpxb = NULL; /* xfer buffer */ +uint16 rpcs1[RP_NUMDR] = { 0 }; /* control/status 1 */ +uint16 rpda[RP_NUMDR] = { 0 }; /* track/sector */ +uint16 rpds[RP_NUMDR] = { 0 }; /* drive status */ +uint16 rper1[RP_NUMDR] = { 0 }; /* error status 1 */ +uint16 rmhr[RP_NUMDR] = { 0 }; /* holding reg */ +uint16 rpmr[RP_NUMDR] = { 0 }; /* maint reg */ +uint16 rmmr2[RP_NUMDR] = { 0 }; /* maint reg 2 */ +uint16 rpof[RP_NUMDR] = { 0 }; /* offset */ +uint16 rpdc[RP_NUMDR] = { 0 }; /* cylinder */ +uint16 rper2[RP_NUMDR] = { 0 }; /* error status 2 */ +uint16 rper3[RP_NUMDR] = { 0 }; /* error status 3 */ +uint16 rpec1[RP_NUMDR] = { 0 }; /* ECC correction 1 */ +uint16 rpec2[RP_NUMDR] = { 0 }; /* ECC correction 2 */ +int32 rp_stopioe = 1; /* stop on error */ +int32 rp_swait = 10; /* seek time */ +int32 rp_rwait = 10; /* rotate time */ static const char *rp_fname[CS1_N_FNC] = { - "NOP", "UNLD", "SEEK", "RECAL", "DCLR", "RLS", "OFFS", "RETN", - "PRESET", "PACK", "12", "13", "SCH", "15", "16", "17", - "20", "21", "22", "23", "WRCHK", "25", "26", "27", - "WRITE", "WRHDR", "32", "33", "READ", "RDHDR", "36", "37" }; + "NOP", "UNLD", "SEEK", "RECAL", "DCLR", "RLS", "OFFS", "RETN", + "PRESET", "PACK", "12", "13", "SCH", "15", "16", "17", + "20", "21", "22", "23", "WRCHK", "25", "26", "27", + "WRITE", "WRHDR", "32", "33", "READ", "RDHDR", "36", "37" + }; extern FILE *sim_deb; @@ -366,109 +369,113 @@ t_stat rp_set_bad (UNIT *uptr, int32 val, char *cptr, void *desc); int32 rp_abort (void); 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 + rp_dev RP device descriptor + rp_unit RP unit list + rp_reg RP register list + rp_mod RP modifier list */ DIB rp_dib = { MBA_RP, 0, &rp_mbrd, &rp_mbwr, 0, 0, 0, { &rp_abort } }; UNIT rp_unit[] = { - { UDATA (&rp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_AUTO+ - UNIT_ROABLE+(INIT_DTYPE << UNIT_V_DTYPE), INIT_SIZE) }, - { UDATA (&rp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_AUTO+ - UNIT_ROABLE+(INIT_DTYPE << UNIT_V_DTYPE), INIT_SIZE) }, - { UDATA (&rp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_AUTO+ - UNIT_ROABLE+(INIT_DTYPE << UNIT_V_DTYPE), INIT_SIZE) }, - { UDATA (&rp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_AUTO+ - UNIT_ROABLE+(INIT_DTYPE << UNIT_V_DTYPE), INIT_SIZE) }, - { UDATA (&rp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_AUTO+ - UNIT_ROABLE+(INIT_DTYPE << UNIT_V_DTYPE), INIT_SIZE) }, - { UDATA (&rp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_AUTO+ - UNIT_ROABLE+(INIT_DTYPE << UNIT_V_DTYPE), INIT_SIZE) }, - { UDATA (&rp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_AUTO+ - UNIT_ROABLE+(INIT_DTYPE << UNIT_V_DTYPE), INIT_SIZE) }, - { UDATA (&rp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_AUTO+ - UNIT_ROABLE+(INIT_DTYPE << UNIT_V_DTYPE), INIT_SIZE) } }; + { UDATA (&rp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_AUTO+ + UNIT_ROABLE+(INIT_DTYPE << UNIT_V_DTYPE), INIT_SIZE) }, + { UDATA (&rp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_AUTO+ + UNIT_ROABLE+(INIT_DTYPE << UNIT_V_DTYPE), INIT_SIZE) }, + { UDATA (&rp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_AUTO+ + UNIT_ROABLE+(INIT_DTYPE << UNIT_V_DTYPE), INIT_SIZE) }, + { UDATA (&rp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_AUTO+ + UNIT_ROABLE+(INIT_DTYPE << UNIT_V_DTYPE), INIT_SIZE) }, + { UDATA (&rp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_AUTO+ + UNIT_ROABLE+(INIT_DTYPE << UNIT_V_DTYPE), INIT_SIZE) }, + { UDATA (&rp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_AUTO+ + UNIT_ROABLE+(INIT_DTYPE << UNIT_V_DTYPE), INIT_SIZE) }, + { UDATA (&rp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_AUTO+ + UNIT_ROABLE+(INIT_DTYPE << UNIT_V_DTYPE), INIT_SIZE) }, + { UDATA (&rp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_AUTO+ + UNIT_ROABLE+(INIT_DTYPE << UNIT_V_DTYPE), INIT_SIZE) } + }; REG rp_reg[] = { - { BRDATA (CS1, rpcs1, DEV_RDX, 16, RP_NUMDR) }, - { BRDATA (DA, rpda, DEV_RDX, 16, RP_NUMDR) }, - { BRDATA (DS, rpds, DEV_RDX, 16, RP_NUMDR) }, - { BRDATA (ER1, rper1, DEV_RDX, 16, RP_NUMDR) }, - { BRDATA (HR, rmhr, DEV_RDX, 16, RP_NUMDR) }, - { BRDATA (OF, rpof, DEV_RDX, 16, RP_NUMDR) }, - { BRDATA (DC, rpdc, DEV_RDX, 16, RP_NUMDR) }, - { BRDATA (ER2, rper2, DEV_RDX, 16, RP_NUMDR) }, - { BRDATA (ER3, rper3, DEV_RDX, 16, RP_NUMDR) }, - { BRDATA (EC1, rpec1, DEV_RDX, 16, RP_NUMDR) }, - { BRDATA (EC2, rpec2, DEV_RDX, 16, RP_NUMDR) }, - { BRDATA (MR, rpmr, DEV_RDX, 16, RP_NUMDR) }, - { BRDATA (MR2, rmmr2, DEV_RDX, 16, RP_NUMDR) }, - { DRDATA (STIME, rp_swait, 24), REG_NZ + PV_LEFT }, - { DRDATA (RTIME, rp_rwait, 24), REG_NZ + PV_LEFT }, - { URDATA (CAPAC, rp_unit[0].capac, 10, T_ADDR_W, 0, - RP_NUMDR, PV_LEFT | REG_HRO) }, - { FLDATA (STOP_IOE, rp_stopioe, 0) }, - { GRDATA (CTRLTYPE, rp_dib.lnt, DEV_RDX, 16, 0), REG_HRO }, - { NULL } }; + { BRDATA (CS1, rpcs1, DEV_RDX, 16, RP_NUMDR) }, + { BRDATA (DA, rpda, DEV_RDX, 16, RP_NUMDR) }, + { BRDATA (DS, rpds, DEV_RDX, 16, RP_NUMDR) }, + { BRDATA (ER1, rper1, DEV_RDX, 16, RP_NUMDR) }, + { BRDATA (HR, rmhr, DEV_RDX, 16, RP_NUMDR) }, + { BRDATA (OF, rpof, DEV_RDX, 16, RP_NUMDR) }, + { BRDATA (DC, rpdc, DEV_RDX, 16, RP_NUMDR) }, + { BRDATA (ER2, rper2, DEV_RDX, 16, RP_NUMDR) }, + { BRDATA (ER3, rper3, DEV_RDX, 16, RP_NUMDR) }, + { BRDATA (EC1, rpec1, DEV_RDX, 16, RP_NUMDR) }, + { BRDATA (EC2, rpec2, DEV_RDX, 16, RP_NUMDR) }, + { BRDATA (MR, rpmr, DEV_RDX, 16, RP_NUMDR) }, + { BRDATA (MR2, rmmr2, DEV_RDX, 16, RP_NUMDR) }, + { DRDATA (STIME, rp_swait, 24), REG_NZ + PV_LEFT }, + { DRDATA (RTIME, rp_rwait, 24), REG_NZ + PV_LEFT }, + { URDATA (CAPAC, rp_unit[0].capac, 10, T_ADDR_W, 0, + RP_NUMDR, PV_LEFT | REG_HRO) }, + { FLDATA (STOP_IOE, rp_stopioe, 0) }, + { GRDATA (CTRLTYPE, rp_dib.lnt, DEV_RDX, 16, 0), REG_HRO }, + { NULL } + }; MTAB rp_mod[] = { - { MTAB_XTD|MTAB_VDV, 0, "MASSBUS", "MASSBUS", NULL, &mba_show_num }, - { 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 }, - { 0 } }; + { MTAB_XTD|MTAB_VDV, 0, "MASSBUS", "MASSBUS", NULL, &mba_show_num }, + { 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 }, + { 0 } + }; DEVICE rp_dev = { - "RP", rp_unit, rp_reg, rp_mod, - RP_NUMDR, DEV_RDX, 30, 1, DEV_RDX, 16, - NULL, NULL, &rp_reset, - &rp_boot, &rp_attach, &rp_detach, - &rp_dib, DEV_DISABLE | DEV_UBUS | DEV_QBUS | DEV_MBUS | DEV_DEBUG }; - + "RP", rp_unit, rp_reg, rp_mod, + RP_NUMDR, DEV_RDX, 30, 1, DEV_RDX, 16, + NULL, NULL, &rp_reset, + &rp_boot, &rp_attach, &rp_detach, + &rp_dib, DEV_DISABLE | DEV_UBUS | DEV_QBUS | DEV_MBUS | DEV_DEBUG + }; + /* Massbus register read */ t_stat rp_mbrd (int32 *data, int32 ofs, int32 drv) @@ -476,80 +483,101 @@ t_stat rp_mbrd (int32 *data, int32 ofs, int32 drv) uint32 val, dtype, i; UNIT *uptr; -rp_update_ds (0, drv); /* update ds */ -uptr = rp_dev.units + drv; /* get unit */ -if (uptr->flags & UNIT_DIS) { /* nx disk */ - *data = 0; - return MBE_NXD; } -dtype = GET_DTYPE (uptr->flags); /* get drive type */ -ofs = ofs & MBA_RMASK; /* mask offset */ -if (drv_tab[dtype].ctrl == RM_CTRL) ofs = ofs + RM_OF; /* RM? convert */ +rp_update_ds (0, drv); /* update ds */ +uptr = rp_dev.units + drv; /* get unit */ +if (uptr->flags & UNIT_DIS) { /* nx disk */ + *data = 0; + return MBE_NXD; + } +dtype = GET_DTYPE (uptr->flags); /* get drive type */ +ofs = ofs & MBA_RMASK; /* mask offset */ +if (drv_tab[dtype].ctrl == RM_CTRL) ofs = ofs + RM_OF; /* RM? convert */ + +switch (ofs) { /* decode offset */ + + case RP_CS1_OF: case RM_CS1_OF: /* RPCS1 */ + val = rpcs1[drv] & CS1_RW; + break; + + case RP_DA_OF: case RM_DA_OF: /* RPDA */ + val = rpda[drv] = rpda[drv] & ~DA_MBZ; + break; + + case RP_DS_OF: case RM_DS_OF: /* RPDS */ + val = rpds[drv]; + break; + + case RP_ER1_OF: case RM_ER1_OF: /* RPER1 */ + val = rper1[drv]; + break; + + case RP_AS_OF: case RM_AS_OF: /* RPAS */ + val = 0; + for (i = 0; i < RP_NUMDR; i++) + if (rpds[i] & DS_ATA) val |= (AS_U0 << i); + break; + + case RP_LA_OF: case RM_LA_OF: /* RPLA */ + val = GET_SECTOR (rp_rwait, dtype) << LA_V_SC; + break; + + case RP_MR_OF: case RM_MR_OF: /* RPMR */ + val = rpmr[drv]; + break; + + case RP_DT_OF: case RM_DT_OF: /* RPDT */ + val = drv_tab[dtype].devtype; + break; + + case RP_SN_OF: case RM_SN_OF: /* RPSN */ + val = 020 | (drv + 1); + break; + + case RP_OF_OF: case RM_OF_OF: /* RPOF */ + val = rpof[drv] = rpof[drv] & ~OF_MBZ; + break; + + case RP_DC_OF: case RM_DC_OF: /* RPDC */ + val = rpdc[drv] = rpdc[drv] & ~DC_MBZ; + break; + + case RP_CC_OF: /* RPCC */ + val = rp_unit[drv].CYL; + break; + + case RP_ER2_OF: case RM_ER2_OF: /* RPER2 */ + val = rper2[drv]; + break; + + case RP_ER3_OF: /* RPER3 */ + val = rper3[drv]; + break; + + case RP_EC1_OF: case RM_EC1_OF: /* RPEC1 */ + val = rpec1[drv]; + break; + + case RP_EC2_OF: case RM_EC2_OF: /* RPEC2 */ + val = rpec2[drv]; + break; + + case RM_HR_OF: /* RMHR */ + val = rmhr[drv] ^ DMASK; + break; + + case RM_MR2_OF: /* RHMR2 */ + val = rmmr2[drv]; + break; + + default: /* all others */ + *data = 0; + return MBE_NXR; + } -switch (ofs) { /* decode offset */ -case RP_CS1_OF: case RM_CS1_OF: /* RPCS1 */ - val = rpcs1[drv] & CS1_RW; - break; -case RP_DA_OF: case RM_DA_OF: /* RPDA */ - val = rpda[drv] = rpda[drv] & ~DA_MBZ; - break; -case RP_DS_OF: case RM_DS_OF: /* RPDS */ - val = rpds[drv]; - break; -case RP_ER1_OF: case RM_ER1_OF: /* RPER1 */ - val = rper1[drv]; - break; -case RP_AS_OF: case RM_AS_OF: /* RPAS */ - val = 0; - for (i = 0; i < RP_NUMDR; i++) - if (rpds[i] & DS_ATA) val |= (AS_U0 << i); - break; -case RP_LA_OF: case RM_LA_OF: /* RPLA */ - val = GET_SECTOR (rp_rwait, dtype) << LA_V_SC; - break; -case RP_MR_OF: case RM_MR_OF: /* RPMR */ - val = rpmr[drv]; - break; -case RP_DT_OF: case RM_DT_OF: /* RPDT */ - val = drv_tab[dtype].devtype; - break; -case RP_SN_OF: case RM_SN_OF: /* RPSN */ - val = 020 | (drv + 1); - break; -case RP_OF_OF: case RM_OF_OF: /* RPOF */ - val = rpof[drv] = rpof[drv] & ~OF_MBZ; - break; -case RP_DC_OF: case RM_DC_OF: /* RPDC */ - val = rpdc[drv] = rpdc[drv] & ~DC_MBZ; - break; -case RP_CC_OF: /* RPCC */ - val = rp_unit[drv].CYL; - break; -case RP_ER2_OF: case RM_ER2_OF: /* RPER2 */ - val = rper2[drv]; - break; -case RP_ER3_OF: /* RPER3 */ - val = rper3[drv]; - break; -case RP_EC1_OF: case RM_EC1_OF: /* RPEC1 */ - val = rpec1[drv]; - break; -case RP_EC2_OF: case RM_EC2_OF: /* RPEC2 */ - val = rpec2[drv]; - break; -case RM_HR_OF: /* RMHR */ - val = rmhr[drv] ^ DMASK; - break; -case RM_MR2_OF: /* RHMR2 */ - val = rmmr2[drv]; - break; -default: /* all others */ - *data = 0; - return MBE_NXR; - } *data = val; return SCPE_OK; } - + /* Massbus register write */ t_stat rp_mbwr (int32 data, int32 ofs, int32 drv) @@ -557,59 +585,70 @@ t_stat rp_mbwr (int32 data, int32 ofs, int32 drv) int32 dtype; UNIT *uptr; -uptr = rp_dev.units + drv; /* get unit */ -if (uptr->flags & UNIT_DIS) return MBE_NXD; /* nx disk */ -if ((ofs != RP_AS_OF) && sim_is_active (uptr)) { /* unit busy? */ - rp_set_er (ER1_RMR, drv); /* won't write */ - rp_update_ds (0, drv); - return SCPE_OK; } -rmhr[drv] = data; /* save write */ -dtype = GET_DTYPE (uptr->flags); /* get drive type */ -ofs = ofs & MBA_RMASK; /* mask offset */ -if (drv_tab[dtype].ctrl == RM_CTRL) ofs = ofs + RM_OF; /* RM? convert */ +uptr = rp_dev.units + drv; /* get unit */ +if (uptr->flags & UNIT_DIS) return MBE_NXD; /* nx disk */ +if ((ofs != RP_AS_OF) && sim_is_active (uptr)) { /* unit busy? */ + rp_set_er (ER1_RMR, drv); /* won't write */ + rp_update_ds (0, drv); + return SCPE_OK; + } +rmhr[drv] = data; /* save write */ +dtype = GET_DTYPE (uptr->flags); /* get drive type */ +ofs = ofs & MBA_RMASK; /* mask offset */ +if (drv_tab[dtype].ctrl == RM_CTRL) ofs = ofs + RM_OF; /* RM? convert */ -switch (ofs) { /* decode PA<5:1> */ -case RP_CS1_OF: case RM_CS1_OF: /* RPCS1 */ - rpcs1[drv] = data & CS1_RW; - if (data & CS1_GO) return rp_go (drv); /* start op */ - break; -case RP_DA_OF: case RM_DA_OF: /* RPDA */ - rpda[drv] = data & ~DA_MBZ; - break; -case RP_AS_OF: case RM_AS_OF: /* RPAS */ - rp_clr_as (data); - break; -case RP_MR_OF: case RM_MR_OF: /* RPMR */ - rpmr[drv] = data; - break; -case RP_OF_OF: case RM_OF_OF: /* RPOF */ - rpof[drv] = data & ~OF_MBZ; - break; -case RP_DC_OF: case RM_DC_OF: /* RPDC */ - rpdc[drv] = data & ~DC_MBZ; - break; -case RM_MR2_OF: /* RMMR2 */ - rmmr2[drv] = data; - break; -case RP_ER1_OF: case RM_ER1_OF: /* RPER1 */ -case RP_DS_OF: case RM_DS_OF: /* RPDS */ -case RP_LA_OF: case RM_LA_OF: /* RPLA */ -case RP_DT_OF: case RM_DT_OF: /* RPDT */ -case RP_SN_OF: case RM_SN_OF: /* RPSN */ -case RP_CC_OF: /* RPCC */ -case RP_ER2_OF: case RM_ER2_OF: /* RPER2 */ -case RP_ER3_OF: /* RPER3 */ -case RP_EC1_OF: case RM_EC1_OF: /* RPEC1 */ -case RP_EC2_OF: case RM_EC2_OF: /* RPEC2 */ -case RM_HR_OF: /* RMHR */ - break; /* read only */ -default: /* all others */ - return MBE_NXR; - } /* end switch */ -rp_update_ds (0, drv); /* update status */ +switch (ofs) { /* decode PA<5:1> */ + + case RP_CS1_OF: case RM_CS1_OF: /* RPCS1 */ + rpcs1[drv] = data & CS1_RW; + if (data & CS1_GO) return rp_go (drv); /* start op */ + break; + + case RP_DA_OF: case RM_DA_OF: /* RPDA */ + rpda[drv] = data & ~DA_MBZ; + break; + + case RP_AS_OF: case RM_AS_OF: /* RPAS */ + rp_clr_as (data); + break; + + case RP_MR_OF: case RM_MR_OF: /* RPMR */ + rpmr[drv] = data; + break; + + case RP_OF_OF: case RM_OF_OF: /* RPOF */ + rpof[drv] = data & ~OF_MBZ; + break; + + case RP_DC_OF: case RM_DC_OF: /* RPDC */ + rpdc[drv] = data & ~DC_MBZ; + break; + + case RM_MR2_OF: /* RMMR2 */ + rmmr2[drv] = data; + break; + + case RP_ER1_OF: case RM_ER1_OF: /* RPER1 */ + case RP_DS_OF: case RM_DS_OF: /* RPDS */ + case RP_LA_OF: case RM_LA_OF: /* RPLA */ + case RP_DT_OF: case RM_DT_OF: /* RPDT */ + case RP_SN_OF: case RM_SN_OF: /* RPSN */ + case RP_CC_OF: /* RPCC */ + case RP_ER2_OF: case RM_ER2_OF: /* RPER2 */ + case RP_ER3_OF: /* RPER3 */ + case RP_EC1_OF: case RM_EC1_OF: /* RPEC1 */ + case RP_EC2_OF: case RM_EC2_OF: /* RPEC2 */ + case RM_HR_OF: /* RMHR */ + break; /* read only */ + + default: /* all others */ + return MBE_NXR; + } /* end switch */ + +rp_update_ds (0, drv); /* update status */ return SCPE_OK; } - + /* Initiate operation - unit not busy, function set */ t_stat rp_go (int32 drv) @@ -617,86 +656,95 @@ t_stat rp_go (int32 drv) int32 dc, fnc, dtype, t; UNIT *uptr; -fnc = GET_FNC (rpcs1[drv]); /* get function */ +fnc = GET_FNC (rpcs1[drv]); /* get function */ if (DEBUG_PRS (rp_dev)) fprintf (sim_deb, - ">>RP%d STRT: fnc=%s, ds=%o, cyl=%o, da=%o, er=%o\n", - drv, rp_fname[fnc], rpds[drv], rpdc[drv], rpda[drv], rper1[drv]); -uptr = rp_dev.units + drv; /* get unit */ -rp_clr_as (AS_U0 << drv); /* clear attention */ -dtype = GET_DTYPE (uptr->flags); /* get drive type */ -dc = rpdc[drv]; /* assume seek, sch */ -if ((fnc != FNC_DCLR) && (rpds[drv] & DS_ERR)) { /* err & ~clear? */ - rp_set_er (ER1_ILF, drv); /* not allowed */ - rp_update_ds (DS_ATA, drv); /* set attention */ - return MBE_GOE; } + ">>RP%d STRT: fnc=%s, ds=%o, cyl=%o, da=%o, er=%o\n", + drv, rp_fname[fnc], rpds[drv], rpdc[drv], rpda[drv], rper1[drv]); +uptr = rp_dev.units + drv; /* get unit */ +rp_clr_as (AS_U0 << drv); /* clear attention */ +dtype = GET_DTYPE (uptr->flags); /* get drive type */ +dc = rpdc[drv]; /* assume seek, sch */ +if ((fnc != FNC_DCLR) && (rpds[drv] & DS_ERR)) { /* err & ~clear? */ + rp_set_er (ER1_ILF, drv); /* not allowed */ + rp_update_ds (DS_ATA, drv); /* set attention */ + return MBE_GOE; + } -switch (fnc) { /* case on function */ -case FNC_DCLR: /* drive clear */ - rpda[drv] = 0; /* clear disk addr */ - rper1[drv] = rper2[drv] = rper3[drv] = 0; /* clear errors */ -case FNC_NOP: /* no operation */ -case FNC_RELEASE: /* port release */ - return SCPE_OK; +switch (fnc) { /* case on function */ -case FNC_PRESET: /* read-in preset */ - rpdc[drv] = 0; /* clear disk addr */ - rpda[drv] = 0; - rpof[drv] = 0; /* clear offset */ -case FNC_PACK: /* pack acknowledge */ - rpds[drv] = rpds[drv] | DS_VV; /* set volume valid */ - return SCPE_OK; + case FNC_DCLR: /* drive clear */ + rpda[drv] = 0; /* clear disk addr */ + rper1[drv] = rper2[drv] = rper3[drv] = 0; /* clear errors */ + case FNC_NOP: /* no operation */ + case FNC_RELEASE: /* port release */ + return SCPE_OK; -case FNC_OFFSET: /* offset mode */ -case FNC_RETURN: - if ((uptr->flags & UNIT_ATT) == 0) { /* not attached? */ - rp_set_er (ER1_UNS, drv); /* unsafe */ - break; } - rpds[drv] = (rpds[drv] & ~DS_RDY) | DS_PIP; /* set positioning */ - sim_activate (uptr, rp_swait); /* time operation */ - return SCPE_OK; + case FNC_PRESET: /* read-in preset */ + rpdc[drv] = 0; /* clear disk addr */ + rpda[drv] = 0; + rpof[drv] = 0; /* clear offset */ + case FNC_PACK: /* pack acknowledge */ + rpds[drv] = rpds[drv] | DS_VV; /* set volume valid */ + return SCPE_OK; -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? */ - rp_set_er (ER1_UNS, drv); /* unsafe */ - break; } - if ((GET_CY (dc) >= drv_tab[dtype].cyl) || /* bad cylinder */ - (GET_SF (rpda[drv]) >= drv_tab[dtype].surf) || /* bad surface */ + case FNC_OFFSET: /* offset mode */ + case FNC_RETURN: + if ((uptr->flags & UNIT_ATT) == 0) { /* not attached? */ + rp_set_er (ER1_UNS, drv); /* unsafe */ + break; + } + rpds[drv] = (rpds[drv] & ~DS_RDY) | DS_PIP; /* set positioning */ + sim_activate (uptr, rp_swait); /* time operation */ + return SCPE_OK; + + 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? */ + rp_set_er (ER1_UNS, drv); /* unsafe */ + break; + } + if ((GET_CY (dc) >= drv_tab[dtype].cyl) || /* bad cylinder */ + (GET_SF (rpda[drv]) >= drv_tab[dtype].surf) || /* bad surface */ (GET_SC (rpda[drv]) >= drv_tab[dtype].sect)) { /* or bad sector? */ - rp_set_er (ER1_IAE, drv); - 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 SCPE_OK; + rp_set_er (ER1_IAE, drv); + 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 SCPE_OK; -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? */ - rp_set_er (ER1_UNS, drv); /* unsafe */ - break; } - if ((GET_CY (dc) >= drv_tab[dtype].cyl) || /* bad cylinder */ - (GET_SF (rpda[drv]) >= drv_tab[dtype].surf) || /* bad surface */ + 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? */ + rp_set_er (ER1_UNS, drv); /* unsafe */ + break; + } + if ((GET_CY (dc) >= drv_tab[dtype].cyl) || /* bad cylinder */ + (GET_SF (rpda[drv]) >= drv_tab[dtype].surf) || /* bad surface */ (GET_SC (rpda[drv]) >= drv_tab[dtype].sect)) { /* or bad sector? */ - rp_set_er (ER1_IAE, drv); - 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 SCPE_OK; + rp_set_er (ER1_IAE, drv); + 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 SCPE_OK; -default: /* all others */ - rp_set_er (ER1_ILF, drv); /* not supported */ - break; } -rp_update_ds (DS_ATA, drv); /* set attn, req int */ + default: /* all others */ + rp_set_er (ER1_ILF, drv); /* not supported */ + break; + } + +rp_update_ds (DS_ATA, drv); /* set attn, req int */ return MBE_GOE; } @@ -706,7 +754,7 @@ int32 rp_abort (void) { return rp_reset (&rp_dev); } - + /* Service unit timeout Complete movement or data transfer command @@ -719,104 +767,111 @@ t_stat rp_svc (UNIT *uptr) int32 i, fnc, dtype, drv, err; int32 wc, abc, awc, mbc, da; -dtype = GET_DTYPE (uptr->flags); /* get drive type */ -drv = uptr - rp_dev.units; /* get drv number */ -da = GET_DA (rpdc[drv], rpda[drv], dtype) * RP_NUMWD; /* get disk addr */ -fnc = GET_FNC (rpcs1[drv]); /* get function */ +dtype = GET_DTYPE (uptr->flags); /* get drive type */ +drv = (int32) (uptr - rp_dev.units); /* get drv number */ +da = GET_DA (rpdc[drv], rpda[drv], dtype) * RP_NUMWD; /* get disk addr */ +fnc = GET_FNC (rpcs1[drv]); /* get function */ -if ((uptr->flags & UNIT_ATT) == 0) { /* not attached? */ - rp_set_er (ER1_UNS, drv); /* set drive error */ - if (fnc >= FNC_XFER) mba_set_don (rp_dib.ba); /* xfr? set done */ - rp_update_ds (DS_ATA, drv); /* set attn */ - return (rp_stopioe? SCPE_UNATT: SCPE_OK); - } -rpds[drv] = (rpds[drv] & ~DS_PIP) | DS_RDY; /* change drive status */ +if ((uptr->flags & UNIT_ATT) == 0) { /* not attached? */ + rp_set_er (ER1_UNS, drv); /* set drive error */ + if (fnc >= FNC_XFER) mba_set_don (rp_dib.ba); /* xfr? set done */ + rp_update_ds (DS_ATA, drv); /* set attn */ + return (rp_stopioe? SCPE_UNATT: SCPE_OK); + } +rpds[drv] = (rpds[drv] & ~DS_PIP) | DS_RDY; /* change drive status */ -switch (fnc) { /* case on function */ -case FNC_OFFSET: /* offset */ - rp_update_ds (DS_OFM | DS_ATA, drv); - break; -case FNC_RETURN: /* return to centerline */ - rpds[drv] = rpds[drv] & ~DS_OFM; /* clear offset, set attn */ - rp_update_ds (DS_ATA, drv); - break; -case FNC_UNLOAD: /* unload */ - rp_detach (uptr); /* detach unit */ - break; -case FNC_RECAL: /* recalibrate */ -case FNC_SEARCH: /* search */ -case FNC_SEEK: /* seek */ - rp_update_ds (DS_ATA, drv); - break; +switch (fnc) { /* case on function */ -case FNC_WRITE: /* write */ - if (uptr->flags & UNIT_WPRT) { /* write locked? */ - rp_set_er (ER1_WLE, drv); /* set drive error */ - mba_set_exc (rp_dib.ba); /* set exception */ - rp_update_ds (DS_ATA, drv); /* set attn */ - return SCPE_OK; } -case FNC_WCHK: /* write check */ -case FNC_READ: /* read */ -case FNC_READH: /* read headers */ - err = fseek (uptr->fileref, da * sizeof (int16), SEEK_SET); - mbc = mba_get_bc (rp_dib.ba); /* get byte count */ - wc = (mbc + 1) >> 1; /* convert to words */ - if ((da + wc) > drv_tab[dtype].size) { /* disk overrun? */ - rp_set_er (ER1_AOE, drv); /* set err */ - wc = drv_tab[dtype].size - da; /* trim xfer */ - mbc = wc << 1; /* trim mb count */ - if (da >= drv_tab[dtype].size) { /* none left? */ - mba_set_exc (rp_dib.ba); /* set exception */ - rp_update_ds (DS_ATA, drv); /* set attn */ - break; - } - } - if (fnc == FNC_WRITE) { /* write? */ - abc = mba_rdbufW (rp_dib.ba, mbc, rpxb); /* get buffer */ - wc = (abc + 1) >> 1; /* actual # wds */ - 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), awc, uptr->fileref); - err = ferror (uptr->fileref); - } - } /* end if wr */ - else { /* read or wchk */ - awc = fxread (rpxb, sizeof (uint16), wc, uptr->fileref); - err = ferror (uptr->fileref); - for (i = awc; i < wc; i++) rpxb[i] = 0; /* fill buf */ - if (fnc == FNC_WCHK) /* write check? */ - mba_chbufW (rp_dib.ba, mbc, rpxb); /* check vs mem */ - else mba_wrbufW (rp_dib.ba, mbc, rpxb); /* store in mem */ - } /* end if read */ - da = da + wc + (RP_NUMWD - 1); - if (da >= drv_tab[dtype].size) rpds[drv] = rpds[drv] | DS_LST; - da = da / RP_NUMWD; - rpda[drv] = da % drv_tab[dtype].sect; - da = da / drv_tab[dtype].sect; - rpda[drv] = rpda[drv] | ((da % drv_tab[dtype].surf) << DA_V_SF); - rpdc[drv] = da / drv_tab[dtype].surf; - uptr->CYL = rpdc[drv]; + case FNC_OFFSET: /* offset */ + rp_update_ds (DS_OFM | DS_ATA, drv); + break; - if (err != 0) { /* error? */ - rp_set_er (ER1_PAR, drv); /* set drive error */ - mba_set_exc (rp_dib.ba); /* set exception */ - rp_update_ds (DS_ATA, drv); - perror ("RP I/O error"); - clearerr (uptr->fileref); - return SCPE_IOERR; } + case FNC_RETURN: /* return to centerline */ + rpds[drv] = rpds[drv] & ~DS_OFM; /* clear offset, set attn */ + rp_update_ds (DS_ATA, drv); + break; -case FNC_WRITEH: /* write headers stub */ - mba_set_don (rp_dib.ba); /* set done */ - rp_update_ds (0, drv); /* update ds */ - break; } /* end case func */ + case FNC_UNLOAD: /* unload */ + rp_detach (uptr); /* detach unit */ + break; + + case FNC_RECAL: /* recalibrate */ + case FNC_SEARCH: /* search */ + case FNC_SEEK: /* seek */ + rp_update_ds (DS_ATA, drv); + break; + + case FNC_WRITE: /* write */ + if (uptr->flags & UNIT_WPRT) { /* write locked? */ + rp_set_er (ER1_WLE, drv); /* set drive error */ + mba_set_exc (rp_dib.ba); /* set exception */ + rp_update_ds (DS_ATA, drv); /* set attn */ + return SCPE_OK; + } + case FNC_WCHK: /* write check */ + case FNC_READ: /* read */ + case FNC_READH: /* read headers */ + err = fseek (uptr->fileref, da * sizeof (int16), SEEK_SET); + mbc = mba_get_bc (rp_dib.ba); /* get byte count */ + wc = (mbc + 1) >> 1; /* convert to words */ + if ((da + wc) > drv_tab[dtype].size) { /* disk overrun? */ + rp_set_er (ER1_AOE, drv); /* set err */ + wc = drv_tab[dtype].size - da; /* trim xfer */ + mbc = wc << 1; /* trim mb count */ + if (da >= drv_tab[dtype].size) { /* none left? */ + mba_set_exc (rp_dib.ba); /* set exception */ + rp_update_ds (DS_ATA, drv); /* set attn */ + break; + } + } + if (fnc == FNC_WRITE) { /* write? */ + abc = mba_rdbufW (rp_dib.ba, mbc, rpxb); /* get buffer */ + wc = (abc + 1) >> 1; /* actual # wds */ + 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), awc, uptr->fileref); + err = ferror (uptr->fileref); + } + } /* end if wr */ + else { /* read or wchk */ + awc = fxread (rpxb, sizeof (uint16), wc, uptr->fileref); + err = ferror (uptr->fileref); + for (i = awc; i < wc; i++) rpxb[i] = 0; /* fill buf */ + if (fnc == FNC_WCHK) /* write check? */ + mba_chbufW (rp_dib.ba, mbc, rpxb); /* check vs mem */ + else mba_wrbufW (rp_dib.ba, mbc, rpxb); /* store in mem */ + } /* end if read */ + da = da + wc + (RP_NUMWD - 1); + if (da >= drv_tab[dtype].size) rpds[drv] = rpds[drv] | DS_LST; + da = da / RP_NUMWD; + rpda[drv] = da % drv_tab[dtype].sect; + da = da / drv_tab[dtype].sect; + rpda[drv] = rpda[drv] | ((da % drv_tab[dtype].surf) << DA_V_SF); + rpdc[drv] = da / drv_tab[dtype].surf; + uptr->CYL = rpdc[drv]; + + if (err != 0) { /* error? */ + rp_set_er (ER1_PAR, drv); /* set drive error */ + mba_set_exc (rp_dib.ba); /* set exception */ + rp_update_ds (DS_ATA, drv); + perror ("RP I/O error"); + clearerr (uptr->fileref); + return SCPE_IOERR; + } + + case FNC_WRITEH: /* write headers stub */ + mba_set_don (rp_dib.ba); /* set done */ + rp_update_ds (0, drv); /* update ds */ + break; + } /* end case func */ if (DEBUG_PRS (rp_dev)) fprintf (sim_deb, - ">>RP%d DONE: fnc=%s, ds=%o, cyl=%o, da=%o, er=%d\n", - drv, rp_fname[fnc], rpds[drv], rpdc[drv], rpda[drv], rper1[drv]); + ">>RP%d DONE: fnc=%s, ds=%o, cyl=%o, da=%o, er=%d\n", + drv, rp_fname[fnc], rpds[drv], rpdc[drv], rpda[drv], rper1[drv]); return SCPE_OK; } - + /* Set drive error */ void rp_set_er (int32 flag, int32 drv) @@ -834,8 +889,9 @@ void rp_clr_as (int32 mask) uint32 i, as; for (i = as = 0; i < RP_NUMDR; i++) { - if (mask & (AS_U0 << i)) rpds[i] &= ~DS_ATA; - if (rpds[i] & DS_ATA) as = 1; } + if (mask & (AS_U0 << i)) rpds[i] &= ~DS_ATA; + if (rpds[i] & DS_ATA) as = 1; + } mba_upd_ata (rp_dib.ba, as); return; } @@ -863,27 +919,27 @@ int32 i; UNIT *uptr; for (i = 0; i < RP_NUMDR; i++) { - uptr = rp_dev.units + i; - sim_cancel (uptr); - uptr->CYL = 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; - rpcs1[i] = 0; - rper1[i] = 0; - rpof[i] = 0; - rpdc[i] = 0; - rpda[i] = 0; - rpmr[i] = 0; - rper2[i] = 0; - rper3[i] = 0; - rpec1[i] = 0; - rpec2[i] = 0; - rmmr2[i] = 0; - rmhr[i] = 0; - } -if (rpxb == NULL) rpxb = calloc (RP_MAXFR, sizeof (uint16)); + uptr = rp_dev.units + i; + sim_cancel (uptr); + uptr->CYL = 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; + rpcs1[i] = 0; + rper1[i] = 0; + rpof[i] = 0; + rpdc[i] = 0; + rpda[i] = 0; + rpmr[i] = 0; + rper2[i] = 0; + rper3[i] = 0; + rpec1[i] = 0; + rpec2[i] = 0; + rmmr2[i] = 0; + rmhr[i] = 0; + } +if (rpxb == NULL) rpxb = (uint16 *) calloc (RP_MAXFR, sizeof (uint16)); if (rpxb == NULL) return SCPE_MEM; return SCPE_OK; } @@ -896,24 +952,27 @@ 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_MOL | DS_RDY | DS_DPR | /* upd drv status */ - ((uptr->flags & UNIT_WPRT)? DS_WRL: 0); +r = attach_unit (uptr, cptr); /* attach unit */ +if (r != SCPE_OK) return r; /* error? */ +drv = (int32) (uptr - rp_dev.units); /* get drv number */ +rpds[drv] = DS_MOL | DS_RDY | DS_DPR | /* upd drv status */ + ((uptr->flags & UNIT_WPRT)? DS_WRL: 0); rper1[drv] = 0; -rp_update_ds (DS_ATA, drv); /* upd ctlr status */ +rp_update_ds (DS_ATA, drv); /* upd ctlr status */ -if ((p = sim_fsize (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? */ +if ((p = sim_fsize (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; } } + uptr->flags = (uptr->flags & ~UNIT_DTYPE) | (i << UNIT_V_DTYPE); + uptr->capac = drv_tab[i].size; + return SCPE_OK; + } + } return SCPE_OK; } @@ -923,10 +982,10 @@ t_stat rp_detach (UNIT *uptr) { int32 drv; -if (!(uptr->flags & UNIT_ATT)) return SCPE_OK; /* attached? */ -drv = uptr - rp_dev.units; /* get drv number */ +if (!(uptr->flags & UNIT_ATT)) return SCPE_OK; /* attached? */ +drv = (int32) (uptr - rp_dev.units); /* get drv number */ rpds[drv] = rpds[drv] & ~(DS_MOL | DS_RDY | DS_WRL | DS_VV | DS_OFM); -rp_update_ds (DS_ATA, drv); /* request intr */ +rp_update_ds (DS_ATA, drv); /* request intr */ return detach_unit (uptr); } @@ -935,7 +994,6 @@ return detach_unit (uptr); t_stat rp_set_size (UNIT *uptr, int32 val, char *cptr, void *desc) { int32 dtype = GET_DTYPE (val); -int32 drv = rp_dev.units - uptr; if (uptr->flags & UNIT_ATT) return SCPE_ALATT; uptr->capac = drv_tab[dtype].size; @@ -953,35 +1011,35 @@ return pdp11_bad_block (uptr, drv_tab[GET_DTYPE (uptr->flags)].sect, RP_NUMWD); #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 (uint16)) +#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 (uint16)) static const uint16 boot_rom[] = { - 0042102, /* "BD" */ - 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 */ -}; + 0042102, /* "BD" */ + 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) { @@ -994,8 +1052,8 @@ for (i = 0; i < BOOT_LEN; i++) M[(BOOT_START >> 1) + i] = boot_rom[i]; M[BOOT_UNIT >> 1] = unitno & (RP_NUMDR - 1); M[BOOT_CSR >> 1] = mba_get_csr (rp_dib.ba) & DMASK; if (drv_tab[GET_DTYPE (uptr->flags)].ctrl == RP_CTRL) - M[BOOT_START >> 1] = 042102; /* "BD" */ -else M[BOOT_START >> 1] = 042122; /* "RD" */ + M[BOOT_START >> 1] = 042102; /* "BD" */ +else M[BOOT_START >> 1] = 042122; /* "RD" */ saved_PC = BOOT_ENTRY; return SCPE_OK; } diff --git a/PDP11/pdp11_rq.c b/PDP11/pdp11_rq.c index eb573689..4caea234 100644 --- a/PDP11/pdp11_rq.c +++ b/PDP11/pdp11_rq.c @@ -20,72 +20,74 @@ 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 + 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 + rq RQDX3 disk controller - 17-Jan-05 RMS Added more RA and RD disks - 31-Oct-04 RMS Added -L switch (LBNs) to RAUSER size specification - 01-Oct-04 RMS Revised Unibus interface - Changed to identify as UDA50 in Unibus configurations - Changed width to be 16b in all configurations - Changed default timing for VAX - 24-Jul-04 RMS VAX controllers luns start with 0 (from Andreas Cejna) - 05-Feb-04 RMS Revised for file I/O library - 25-Jan-04 RMS Revised for device debug support - 12-Jan-04 RMS Fixed bug in interrupt control (found by Tom Evans) - 07-Oct-03 RMS Fixed problem with multiple RAUSER drives - 17-Sep-03 RMS Fixed MB to LBN conversion to be more accurate - 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 + 16-Aug-05 RMS Fixed C++ declaration and cast problems + 22-Jul-05 RMS Fixed warning from Solaris C (from Doug Gwyn) + 17-Jan-05 RMS Added more RA and RD disks + 31-Oct-04 RMS Added -L switch (LBNs) to RAUSER size specification + 01-Oct-04 RMS Revised Unibus interface + Changed to identify as UDA50 in Unibus configurations + Changed width to be 16b in all configurations + Changed default timing for VAX + 24-Jul-04 RMS VAX controllers luns start with 0 (from Andreas Cejna) + 05-Feb-04 RMS Revised for file I/O library + 25-Jan-04 RMS Revised for device debug support + 12-Jan-04 RMS Fixed bug in interrupt control (found by Tom Evans) + 07-Oct-03 RMS Fixed problem with multiple RAUSER drives + 17-Sep-03 RMS Fixed MB to LBN conversion to be more accurate + 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 */ +#if defined (VM_PDP10) /* PDP10 version */ #error "RQDX3 not supported on PDP-10!" -#elif defined (VM_VAX) /* VAX version */ +#elif defined (VM_VAX) /* VAX version */ #include "vax_defs.h" -#define RQ_QTIME 100 -#define RQ_XTIME 200 -#define OLDPC fault_PC +#define RQ_QTIME 100 +#define RQ_XTIME 200 +#define OLDPC fault_PC extern int32 fault_PC; -#else /* PDP-11 version */ +#else /* PDP-11 version */ #include "pdp11_defs.h" -#define RQ_QTIME 200 -#define RQ_XTIME 500 -#define OLDPC MMR2 +#define RQ_QTIME 200 +#define RQ_XTIME 500 +#define OLDPC MMR2 extern int32 MMR2; extern int32 cpu_opt; #endif #if !defined (RQ_NUMCT) -#define RQ_NUMCT 4 +#define RQ_NUMCT 4 #elif (RQ_NUMCT > 4) #error "Assertion failure: RQ_NUMCT exceeds 4" #endif @@ -93,67 +95,68 @@ extern int32 cpu_opt; #include "pdp11_uqssp.h" #include "pdp11_mscp.h" -#define UF_MSK (UF_CMR|UF_CMW) /* settable flags */ +#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_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_SH_ALL 017 /* show all */ -#define RQ_CLASS 1 /* RQ class */ -#define RQU_UQPM 6 /* UB port model */ -#define RQQ_UQPM 19 /* QB port model */ -#define RQ_UQPM (UNIBUS? RQU_UQPM: RQQ_UQPM) -#define RQU_MODEL 6 /* UB MSCP ctrl model */ -#define RQQ_MODEL 19 /* QB MSCP ctrl model */ -#define RQ_MODEL (UNIBUS? RQU_MODEL: RQQ_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 RQ_CLASS 1 /* RQ class */ +#define RQU_UQPM 6 /* UB port model */ +#define RQQ_UQPM 19 /* QB port model */ +#define RQ_UQPM (UNIBUS? RQU_UQPM: RQQ_UQPM) +#define RQU_MODEL 6 /* UB MSCP ctrl model */ +#define RQQ_MODEL 19 /* QB MSCP ctrl model */ +#define RQ_MODEL (UNIBUS? RQU_MODEL: RQQ_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 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 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 ERR 0 /* must be SCPE_OK! */ +#define OK 1 + +#define RQ_TIMER (RQ_NUMDR) +#define RQ_QUEUE (RQ_TIMER + 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, @@ -162,36 +165,37 @@ extern int32 cpu_opt; 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)) +#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 */ + 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 +#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 disk 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. + 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. @@ -200,341 +204,342 @@ struct rqpkt { 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 */ - +#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 (x = not implemented): - 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 -x RD32 17 6 820 ? ? ? 83236 -x RD33 17 7 1170 ? ? ? 138565 - RD53 17 7 1024 7 1 5*8 138672 - RD54 17 15 1225 15 1 7*8 311200 + 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 +x RD32 17 6 820 ? ? ? 83236 +x RD33 17 7 1170 ? ? ? 138565 + 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. - RA60 42(+1) 6 1600 6 1 1008 400176 -x RA70 33(+1) 11 1507+ 11 1 ? 547041 - RA81 51(+1) 14 1258 14 1 2856 891072 - RA82 57(+1) 15 1435 15 1 3420 1216665 - RA71 51(+1) 14 1921 14 1 1428 1367310 - RA72 51(+1) 20 1921 20 1 2040 1953300 - RA90 69(+1) 13 2656 13 1 1794 2376153 - RA92 73(+1) 13 3101 13 1 949 2940951 -x RA73 70(+1) 21 2667+ 21 1 ? 3920490 + RA60 42(+1) 6 1600 6 1 1008 400176 +x RA70 33(+1) 11 1507+ 11 1 ? 547041 + RA81 51(+1) 14 1258 14 1 2856 891072 + RA82 57(+1) 15 1435 15 1 3420 1216665 + RA71 51(+1) 14 1921 14 1 1428 1367310 + RA72 51(+1) 20 1921 20 1 2040 1953300 + RA90 69(+1) 13 2656 13 1 1794 2376153 + RA92 73(+1) 13 3101 13 1 949 2940951 +x RA73 70(+1) 21 2667+ 21 1 ? 3920490 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 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 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 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 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 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 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 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 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 3480 /* cyl 1427-1430 */ -#define RA82_DBN 3480 /* cyl 1431-1434 */ -#define RA82_LBN 1216665 /* 57*15*1423 */ -#define RA82_RCTS 3420 /* cyl 1423-1426 */ -#define RA82_RCTC 1 -#define RA82_RBN 21345 /* 1 *15*1423 */ -#define RA82_MOD 11 -#define RA82_MED 0x25641052 -#define RA82_FLGS RQDF_SDI +#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 3480 /* cyl 1427-1430 */ +#define RA82_DBN 3480 /* cyl 1431-1434 */ +#define RA82_LBN 1216665 /* 57*15*1423 */ +#define RA82_RCTS 3420 /* cyl 1423-1426 */ +#define RA82_RCTC 1 +#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 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 2080 /* cyl 1917-1918? */ -#define RA72_DBN 2080 /* cyl 1920-1921? */ -#define RA72_LBN 1953300 /* 51*20*1915 */ -#define RA72_RCTS 2040 /* cyl 1915-1916? */ -#define RA72_RCTC 1 -#define RA72_RBN 38300 /* 1 *20*1915 */ -#define RA72_MOD 37 -#define RA72_MED 0x25641048 -#define RA72_FLGS RQDF_SDI +#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 2080 /* cyl 1917-1918? */ +#define RA72_DBN 2080 /* cyl 1920-1921? */ +#define RA72_LBN 1953300 /* 51*20*1915 */ +#define RA72_RCTS 2040 /* cyl 1915-1916? */ +#define RA72_RCTC 1 +#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 1820 /* cyl 2651-2652? */ -#define RA90_DBN 1820 /* cyl 2653-2654? */ -#define RA90_LBN 2376153 /* 69*13*2649 */ -#define RA90_RCTS 1794 /* cyl 2649-2650? */ -#define RA90_RCTC 1 -#define RA90_RBN 34437 /* 1 *13*2649 */ -#define RA90_MOD 19 -#define RA90_MED 0x2564105A -#define RA90_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 1820 /* cyl 2651-2652? */ +#define RA90_DBN 1820 /* cyl 2653-2654? */ +#define RA90_LBN 2376153 /* 69*13*2649 */ +#define RA90_RCTS 1794 /* cyl 2649-2650? */ +#define RA90_RCTC 1 +#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 788 -#define RA92_LBN 2940951 /* 73*13*3099 */ -#define RA92_RCTS 949 /* cyl 3099? */ -#define RA92_RCTC 1 -#define RA92_RBN 40287 /* 1 *13*3099 */ -#define RA92_MOD 29 -#define RA92_MED 0x2564105C -#define RA92_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 788 +#define RA92_LBN 2940951 /* 73*13*3099 */ +#define RA92_RCTS 949 /* cyl 3099? */ +#define RA92_RCTC 1 +#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 /* from RA82 */ -#define RA8U_SURF 15 -#define RA8U_CYL 1435 /* from RA82 */ -#define RA8U_TPG RA8U_SURF -#define RA8U_GPC 1 -#define RA8U_XBN 0 -#define RA8U_DBN 0 -#define RA8U_LBN 1216665 /* from RA82 */ -#define RA8U_RCTS 400 -#define RA8U_RCTC 8 -#define RA8U_RBN 21345 -#define RA8U_MOD 11 /* RA82 */ -#define RA8U_MED 0x25641052 /* RA82 */ -#define RA8U_FLGS RQDF_SDI -#define RA8U_MINC 10000 /* min cap LBNs */ -#define RA8U_MAXC 4000000 /* max cap LBNs */ -#define RA8U_EMAXC 2000000000 /* ext max cap */ +#define RA8U_DTYPE 12 /* user defined */ +#define RA8U_SECT 57 /* from RA82 */ +#define RA8U_SURF 15 +#define RA8U_CYL 1435 /* from RA82 */ +#define RA8U_TPG RA8U_SURF +#define RA8U_GPC 1 +#define RA8U_XBN 0 +#define RA8U_DBN 0 +#define RA8U_LBN 1216665 /* from RA82 */ +#define RA8U_RCTS 400 +#define RA8U_RCTC 8 +#define RA8U_RBN 21345 +#define RA8U_MOD 11 /* RA82 */ +#define RA8U_MED 0x25641052 /* RA82 */ +#define RA8U_FLGS RQDF_SDI +#define RA8U_MINC 10000 /* min cap LBNs */ +#define RA8U_MAXC 4000000 /* max cap LBNs */ +#define RA8U_EMAXC 2000000000 /* ext max cap */ -#define RA60_DTYPE 13 /* SDI drive */ -#define RA60_SECT 42 /* +1 spare/track */ -#define RA60_SURF 6 -#define RA60_CYL 1600 /* 0-1587 user */ -#define RA60_TPG RA60_SURF -#define RA60_GPC 1 -#define RA60_XBN 1032 /* cyl 1592-1595 */ -#define RA60_DBN 1032 /* cyl 1596-1599 */ -#define RA60_LBN 400176 /* 42*6*1588 */ -#define RA60_RCTS 1008 /* cyl 1588-1591 */ -#define RA60_RCTC 1 -#define RA60_RBN 9528 /* 1 *6*1588 */ -#define RA60_MOD 4 -#define RA60_MED 0x22A4103C -#define RA60_FLGS (RQDF_RMV | RQDF_SDI) +#define RA60_DTYPE 13 /* SDI drive */ +#define RA60_SECT 42 /* +1 spare/track */ +#define RA60_SURF 6 +#define RA60_CYL 1600 /* 0-1587 user */ +#define RA60_TPG RA60_SURF +#define RA60_GPC 1 +#define RA60_XBN 1032 /* cyl 1592-1595 */ +#define RA60_DBN 1032 /* cyl 1596-1599 */ +#define RA60_LBN 400176 /* 42*6*1588 */ +#define RA60_RCTS 1008 /* cyl 1588-1591 */ +#define RA60_RCTC 1 +#define RA60_RBN 9528 /* 1 *6*1588 */ +#define RA60_MOD 4 +#define RA60_MED 0x22A4103C +#define RA60_FLGS (RQDF_RMV | RQDF_SDI) -#define RA81_DTYPE 14 /* SDI drive */ -#define RA81_SECT 51 /* +1 spare/track */ -#define RA81_SURF 14 -#define RA81_CYL 1258 /* 0-1247 user */ -#define RA81_TPG RA81_SURF -#define RA81_GPC 1 -#define RA81_XBN 2436 /* cyl 1252-1254? */ -#define RA81_DBN 2436 /* cyl 1255-1256? */ -#define RA81_LBN 891072 /* 51*14*1248 */ -#define RA81_RCTS 2856 /* cyl 1248-1251? */ -#define RA81_RCTC 1 -#define RA81_RBN 17472 /* 1 *14*1248 */ -#define RA81_MOD 5 -#define RA81_MED 0x25641051 -#define RA81_FLGS RQDF_SDI +#define RA81_DTYPE 14 /* SDI drive */ +#define RA81_SECT 51 /* +1 spare/track */ +#define RA81_SURF 14 +#define RA81_CYL 1258 /* 0-1247 user */ +#define RA81_TPG RA81_SURF +#define RA81_GPC 1 +#define RA81_XBN 2436 /* cyl 1252-1254? */ +#define RA81_DBN 2436 /* cyl 1255-1256? */ +#define RA81_LBN 891072 /* 51*14*1248 */ +#define RA81_RCTS 2856 /* cyl 1248-1251? */ +#define RA81_RCTC 1 +#define RA81_RBN 17472 /* 1 *14*1248 */ +#define RA81_MOD 5 +#define RA81_MED 0x25641051 +#define RA81_FLGS RQDF_SDI -#define RA71_DTYPE 15 /* SDI drive */ -#define RA71_SECT 51 /* +1 spare/track */ -#define RA71_SURF 14 -#define RA71_CYL 1921 /* 0-1914 user */ -#define RA71_TPG RA71_SURF -#define RA71_GPC 1 -#define RA71_XBN 1456 /* cyl 1917-1918? */ -#define RA71_DBN 1456 /* cyl 1919-1920? */ -#define RA71_LBN 1367310 /* 51*14*1915 */ -#define RA71_RCTS 1428 /* cyl 1915-1916? */ -#define RA71_RCTC 1 -#define RA71_RBN 26810 /* 1 *14*1915 */ -#define RA71_MOD 40 -#define RA71_MED 0x25641047 -#define RA71_FLGS RQDF_SDI +#define RA71_DTYPE 15 /* SDI drive */ +#define RA71_SECT 51 /* +1 spare/track */ +#define RA71_SURF 14 +#define RA71_CYL 1921 /* 0-1914 user */ +#define RA71_TPG RA71_SURF +#define RA71_GPC 1 +#define RA71_XBN 1456 /* cyl 1917-1918? */ +#define RA71_DBN 1456 /* cyl 1919-1920? */ +#define RA71_LBN 1367310 /* 51*14*1915 */ +#define RA71_RCTS 1428 /* cyl 1915-1916? */ +#define RA71_RCTC 1 +#define RA71_RBN 26810 /* 1 *14*1915 */ +#define RA71_MOD 40 +#define RA71_MED 0x25641047 +#define RA71_FLGS RQDF_SDI 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 */ -}; + 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) + 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" }, { RQ_DRV (RA60), "RA60" }, - { RQ_DRV (RA81), "RA81" }, { RQ_DRV (RA71), "RA71" }, - { 0 } }; - + { 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" }, { RQ_DRV (RA60), "RA60" }, + { RQ_DRV (RA81), "RA81" }, { RQ_DRV (RA71), "RA71" }, + { 0 } + }; + extern int32 int_req[IPL_HLVL]; extern int32 tmr_poll, clk_tps; extern UNIT cpu_unit; @@ -542,37 +547,35 @@ extern FILE *sim_deb; extern uint32 sim_taddr_64; extern int32 sim_switches; -uint16 *rqxb = NULL; /* xfer buffer */ -int32 rq_itime = 200; /* init time, except */ -int32 rq_itime4 = 10; /* stage 4 */ -int32 rq_qtime = RQ_QTIME; /* queue time */ -int32 rq_xtime = RQ_XTIME; /* transfer time */ +uint16 *rqxb = NULL; /* xfer buffer */ +int32 rq_itime = 200; /* init time, except */ +int32 rq_itime4 = 10; /* stage 4 */ +int32 rq_qtime = RQ_QTIME; /* queue time */ +int32 rq_xtime = RQ_XTIME; /* 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 */ +typedef struct { + 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 */ + } MSC; DEVICE rq_dev, rqb_dev, rqc_dev,rqd_dev; @@ -618,7 +621,7 @@ 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); + 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); @@ -629,344 +632,367 @@ 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 + 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 } }; +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) } }; + { 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 } }; + { 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, RA60_DTYPE, NULL, "RA60", - &rq_set_type, NULL, NULL }, - { MTAB_XTD | MTAB_VUN, RA81_DTYPE, NULL, "RA81", - &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, RA71_DTYPE, NULL, "RA71", - &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 }, + { 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, RQ_SH_ALL, "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, RA60_DTYPE, NULL, "RA60", + &rq_set_type, NULL, NULL }, + { MTAB_XTD | MTAB_VUN, RA81_DTYPE, NULL, "RA81", + &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, RA71_DTYPE, NULL, "RA71", + &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 }, + { MTAB_XTD|MTAB_VDV, 004, "ADDRESS", "ADDRESS", + &set_addr, &show_addr, NULL }, #else - { MTAB_XTD|MTAB_VDV, 004, "ADDRESS", NULL, - NULL, &show_addr, NULL }, + { 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 } }; + { 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, 2, DEV_RDX, 16, - NULL, NULL, &rq_reset, - &rq_boot, &rq_attach, &rq_detach, - &rq_dib, DEV_FLTA | DEV_DISABLE | DEV_UBUS | DEV_QBUS | DEV_DEBUG }; - + "RQ", rq_unit, rq_reg, rq_mod, + RQ_NUMDR + 2, DEV_RDX, 31, 2, DEV_RDX, 16, + NULL, NULL, &rq_reset, + &rq_boot, &rq_attach, &rq_detach, + &rq_dib, DEV_FLTA | DEV_DISABLE | DEV_UBUS | DEV_QBUS | DEV_DEBUG + }; + /* RQB data structures - rqb_dev RQB device descriptor - rqb_unit RQB unit list - rqb_reg RQB register list - rqb_mod RQB modifier list + 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 } }; +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) } }; + { 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 } }; + { 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, 2, DEV_RDX, 16, - NULL, NULL, &rq_reset, - &rq_boot, &rq_attach, &rq_detach, - &rqb_dib, DEV_FLTA | DEV_DISABLE | DEV_DIS | DEV_UBUS | DEV_QBUS | DEV_DEBUG }; - + "RQB", rqb_unit, rqb_reg, rq_mod, + RQ_NUMDR + 2, DEV_RDX, 31, 2, DEV_RDX, 16, + NULL, NULL, &rq_reset, + &rq_boot, &rq_attach, &rq_detach, + &rqb_dib, DEV_FLTA | DEV_DISABLE | DEV_DIS | DEV_UBUS | DEV_QBUS | DEV_DEBUG + }; + /* RQC data structures - rqc_dev RQC device descriptor - rqc_unit RQC unit list - rqc_reg RQC register list - rqc_mod RQC modifier list + 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 } }; +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) } }; + { 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 } }; + { 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, 2, DEV_RDX, 16, - NULL, NULL, &rq_reset, - &rq_boot, &rq_attach, &rq_detach, - &rqc_dib, DEV_FLTA | DEV_DISABLE | DEV_DIS | DEV_UBUS | DEV_QBUS | DEV_DEBUG }; - + "RQC", rqc_unit, rqc_reg, rq_mod, + RQ_NUMDR + 2, DEV_RDX, 31, 2, DEV_RDX, 16, + NULL, NULL, &rq_reset, + &rq_boot, &rq_attach, &rq_detach, + &rqc_dib, DEV_FLTA | DEV_DISABLE | DEV_DIS | DEV_UBUS | DEV_QBUS | DEV_DEBUG + }; + /* RQD data structures - rqd_dev RQ device descriptor - rqd_unit RQ unit list - rqd_reg RQ register list - rqd_mod RQ modifier list + 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 } }; +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) } }; + { 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 } }; + { 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, 2, DEV_RDX, 16, - NULL, NULL, &rq_reset, - &rq_boot, &rq_attach, &rq_detach, - &rqd_dib, DEV_FLTA | DEV_DISABLE | DEV_DIS | DEV_UBUS | DEV_QBUS | DEV_DEBUG }; + "RQD", rqd_unit, rqd_reg, rq_mod, + RQ_NUMDR + 2, DEV_RDX, 31, 2, DEV_RDX, 16, + NULL, NULL, &rq_reset, + &rq_boot, &rq_attach, &rq_detach, + &rqd_dib, DEV_FLTA | DEV_DISABLE | DEV_DIS | DEV_UBUS | DEV_QBUS | DEV_DEBUG + }; static DEVICE *rq_devmap[RQ_NUMCT] = { - &rq_dev, &rqb_dev, &rqc_dev, &rqd_dev }; + &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 + &rq_ctx, &rqb_ctx, &rqc_ctx, &rqd_ctx + }; - base + 0 IP read/write - base + 2 SA read/write +/* I/O dispatch routines, 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) @@ -976,19 +1002,24 @@ 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 */ - if (DEBUG_PRD (dptr)) fprintf (sim_deb, - ">>RQ%c: poll started, PC=%X\n", 'A' + cp->cnum, OLDPC); - cp->pip = 1; /* poll host */ - sim_activate (dptr->units + RQ_QUEUE, rq_qtime); } - break; -case 1: /* SA */ - *data = cp->sa; - break; } +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 */ + if (DEBUG_PRD (dptr)) fprintf (sim_deb, + ">>RQ%c: poll started, PC=%X\n", 'A' + cp->cnum, OLDPC); + cp->pip = 1; /* poll host */ + sim_activate (dptr->units + RQ_QUEUE, rq_qtime); + } + break; + + case 1: /* SA */ + *data = cp->sa; + break; + } + return SCPE_OK; } @@ -999,19 +1030,23 @@ 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 (DEBUG_PRD (dptr)) fprintf (sim_deb, - ">>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; } +switch ((PA >> 1) & 01) { /* decode PA<1> */ + + case 0: /* IP */ + rq_reset (rq_devmap[cidx]); /* init device */ + if (DEBUG_PRD (dptr)) fprintf (sim_deb, + ">>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; } @@ -1023,12 +1058,13 @@ 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 */ +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; } @@ -1040,27 +1076,27 @@ 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 */ +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)) /* 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 */ +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)) /* 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. @@ -1081,89 +1117,106 @@ 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 (DEBUG_PRD (dptr)) fprintf (sim_deb, - ">>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 */ +if (cp->csta < CST_UP) { /* still init? */ + switch (cp->csta) { /* controller state? */ -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? */ + 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 (DEBUG_PRD (dptr)) fprintf (sim_deb, + ">>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 (DEBUG_PRD (dptr)) { - fprintf (sim_deb, ">>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_deb, "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 */ + fprintf (sim_deb, ">>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_deb, "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) */ @@ -1175,19 +1228,21 @@ 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 */ +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) @@ -1195,38 +1250,51 @@ 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; } + + 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); } @@ -1235,35 +1303,41 @@ return rq_putpkt (cp, pkt, TRUE); 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 # */ +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 */ +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); } @@ -1272,19 +1346,21 @@ return rq_putpkt (cp, pkt, TRUE); 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 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 */ +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); } @@ -1293,21 +1369,23 @@ return rq_putpkt (cp, pkt, TRUE); 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 # */ +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]; } +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; } + 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); } @@ -1316,33 +1394,36 @@ return rq_putpkt (cp, pkt, TRUE); 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 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 */ +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); @@ -1352,26 +1433,29 @@ return rq_putpkt (cp, pkt, TRUE); 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 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 */ +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); @@ -1383,114 +1467,125 @@ 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; } +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 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 */ +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 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 */ +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 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 */ +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); } @@ -1499,35 +1594,37 @@ return rq_putpkt (cp, pkt, TRUE); 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 = (uint32) (uptr->capac / RQ_NUMBY); /* get max lbn */ +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 = (uint32) (uptr->capac / RQ_NUMBY); /* 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 */ +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! */ + 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 */ @@ -1538,97 +1635,112 @@ MSC *cp = rq_ctxmap[uptr->cnum]; uint32 i, t, tbc, abc, wwc; uint32 err = 0; -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 */ +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 ((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 ((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) || (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 = sim_fseek (uptr->fileref, da, SEEK_SET); /* set pos */ - if (!err) sim_fwrite (rqxb, sizeof (int16), wwc, uptr->fileref); - err = ferror (uptr->fileref); } /* end if erase */ +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 = sim_fseek (uptr->fileref, da, SEEK_SET); /* set pos */ + if (!err) sim_fwrite (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); /* 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 = sim_fseek (uptr->fileref, da, SEEK_SET); - if (!err) sim_fwrite (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 if (cmd == OP_WR) { /* write? */ + t = Map_ReadW (ba, tbc, rqxb); /* 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 = sim_fseek (uptr->fileref, da, SEEK_SET); + if (!err) sim_fwrite (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 = sim_fseek (uptr->fileref, da, SEEK_SET); /* set pos */ - if (!err) { - i = sim_fread (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)) { /* 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)) { /* 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 */ +else { + err = sim_fseek (uptr->fileref, da, SEEK_SET); /* set pos */ + if (!err) { + i = sim_fread (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)) { /* 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)) { /* 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 if */ + } /* 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! */ +if (bc) sim_activate (uptr, rq_xtime); /* more? resched */ +else rq_rw_end (cp, uptr, 0, ST_SUC); /* done! */ return SCPE_OK; } @@ -1636,27 +1748,27 @@ return SCPE_OK; 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 */ +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 */ +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 */ +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) @@ -1664,45 +1776,45 @@ 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 */ +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_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[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); + (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 */ + (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 # */ + (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_D2] = csect << DTE_D2_V_SECT; /* geometry */ cp->pak[pkt].d[DTE_D3] = (ccyl << DTE_D3_V_CYL) | - (csurf << DTE_D3_V_SURF); + (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); } @@ -1713,22 +1825,22 @@ 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 */ +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[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); + (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_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); @@ -1740,18 +1852,18 @@ 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 */ +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[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); + (RQ_MODEL << PLF_CIDD_V_MOD); cp->pak[pkt].d[PLF_VER] = (RQ_SVER << PLF_VER_V_SVER) | - (RQ_HVER << PLF_VER_V_HVER); + (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); @@ -1766,61 +1878,63 @@ 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 */ +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 */ +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 + 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 */ +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 */ +int32 ptr = *lh; /* head of list */ -if (ptr) *lh = cp->pak[ptr].link; /* next */ +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 */ +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 */ +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 */ @@ -1829,16 +1943,17 @@ 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 (!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)) - return rq_fatal (cp, PE_PRE); /* read pkt */ -return rq_putdesc (cp, &cp->cq, desc); /* release desc */ + 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. @@ -1851,29 +1966,31 @@ 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 (pkt == 0) return OK; /* any packet? */ if (DEBUG_PRD (dptr)) fprintf (sim_deb, - ">>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); } + ">>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)) - 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 */ + 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 */ @@ -1883,8 +2000,8 @@ 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)) /* fetch desc */ - return rq_fatal (cp, PE_QRE); /* err? dead */ +if (Map_ReadW (addr, 4, d)) /* fetch desc */ + return rq_fatal (cp, PE_QRE); /* err? dead */ *desc = ((uint32) d[0]) | (((uint32) d[1]) << 16); return OK; } @@ -1901,22 +2018,24 @@ 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[0] = newd & 0xFFFF; /* 32b to 16b */ d[1] = (newd >> 16) & 0xFFFF; -if (Map_WriteW (addr, 4, d)) /* 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)) /* 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); } } +if (Map_WriteW (addr, 4, d)) /* 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)) /* 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) @@ -1925,7 +2044,7 @@ DEVICE *dptr = rq_devmap[cp->cnum]; UNIT *uptr; if ((lu < cp->ubase) || (lu >= (cp->ubase + RQ_NUMDR))) - return NULL; + return NULL; uptr = dptr->units + (lu % RQ_NUMDR); if (uptr->flags & UNIT_DIS) return NULL; return uptr; @@ -1935,10 +2054,10 @@ return uptr; 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... */ +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; } @@ -1946,37 +2065,38 @@ return; void rq_putr_unit (MSC *cp, int32 pkt, UNIT *uptr, uint32 lu, t_bool all) { -uint32 dtyp = GET_DTYPE (uptr->flags); /* get drive type */ -uint32 maxlbn = (uint32) (uptr->capac / RQ_NUMBY); /* get max lbn */ +uint32 dtyp = GET_DTYPE (uptr->flags); /* get drive type */ +uint32 maxlbn = (uint32) (uptr->capac / RQ_NUMBY); /* get max lbn */ -cp->pak[pkt].d[ONL_MLUN] = lu; /* unit */ +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_RSVL] = 0; /* reserved */ cp->pak[pkt].d[ONL_RSVH] = 0; -cp->pak[pkt].d[ONL_UIDA] = lu; /* UID low */ +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, maxlbn); /* user LBNs */ - cp->pak[pkt].d[ONL_VSNL] = 01234 + lu; /* vol serial # */ - cp->pak[pkt].d[ONL_VSNH] = 0; } + (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, maxlbn); /* 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) + 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_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 */ +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; } @@ -1984,8 +2104,8 @@ return; void rq_init_int (MSC *cp) { -if ((cp->s1dat & SA_S1H_IE) && /* int enab & */ - (cp->s1dat & SA_S1H_VEC)) rq_setint (cp); /* ved set? int */ +if ((cp->s1dat & SA_S1H_IE) && /* int enab & */ + (cp->s1dat & SA_S1H_VEC)) rq_setint (cp); /* ved set? int */ return; } @@ -1993,11 +2113,11 @@ return; void rq_ring_int (MSC *cp, struct uq_ring *ring) { -uint32 iadr = cp->comm + ring->ioff; /* addr intr wd */ +uint32 iadr = cp->comm + ring->ioff; /* addr intr wd */ uint16 flag = 1; -Map_WriteW (iadr, 2, &flag); /* write flag */ -if (cp->s1dat & SA_S1H_VEC) rq_setint (cp); /* if enb, intr */ +Map_WriteW (iadr, 2, &flag); /* write flag */ +if (cp->s1dat & SA_S1H_VEC) rq_setint (cp); /* if enb, intr */ return; } @@ -2005,8 +2125,8 @@ return; void rq_setint (MSC *cp) { -cp->irq = 1; /* set ctrl int */ -SET_INT (RQ); /* set master int */ +cp->irq = 1; /* set ctrl int */ +SET_INT (RQ); /* set master int */ return; } @@ -2017,13 +2137,15 @@ 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 */ +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; } @@ -2036,14 +2158,16 @@ 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 */ +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 */ @@ -2053,21 +2177,21 @@ t_bool rq_fatal (MSC *cp, uint32 err) DEVICE *dptr = rq_devmap[cp->cnum]; if (DEBUG_PRD (dptr)) - fprintf (sim_deb, ">>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 */ + fprintf (sim_deb, ">>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 */ +uint32 dtyp = GET_DTYPE (uptr->flags); /* get drive type */ -if (drv_tab[dtyp].flgs & RQDF_RO) return SCPE_NOFNC; /* not on read only */ +if (drv_tab[dtyp].flgs & RQDF_RO) return SCPE_NOFNC; /* not on read only */ return SCPE_OK; } @@ -2075,7 +2199,7 @@ return SCPE_OK; t_stat rq_show_wlk (FILE *st, UNIT *uptr, int32 val, void *desc) { -uint32 dtyp = GET_DTYPE (uptr->flags); /* get drive type */ +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"); @@ -2092,13 +2216,14 @@ uint32 max = sim_taddr_64? RA8U_EMAXC: RA8U_MAXC; t_stat r; if ((val < 0) || ((val != RA8U_DTYPE) && cptr)) - return SCPE_ARG; + return SCPE_ARG; if (uptr->flags & UNIT_ATT) return SCPE_ALATT; if (cptr) { - cap = (uint32) get_uint (cptr, 10, 0xFFFFFFFF, &r); - if ((sim_switches & SWMASK ('L')) == 0) cap = cap * 1954; - if ((r != SCPE_OK) || (cap < RA8U_MINC) || (cap >= max)) return SCPE_ARG; - drv_tab[val].lbn = cap; } + cap = (uint32) get_uint (cptr, 10, 0xFFFFFFFF, &r); + if ((sim_switches & SWMASK ('L')) == 0) cap = cap * 1954; + if ((r != SCPE_OK) || (cap < RA8U_MINC) || (cap >= max)) return SCPE_ARG; + drv_tab[val].lbn = cap; + } uptr->flags = (uptr->flags & ~UNIT_DTYPE) | (val << UNIT_V_DTYPE); uptr->capac = ((t_addr) drv_tab[val].lbn) * RQ_NUMBY; return SCPE_OK; @@ -2116,7 +2241,6 @@ return SCPE_OK; t_stat rq_attach (UNIT *uptr, char *cptr) { -int32 dtyp = GET_DTYPE (uptr->flags); MSC *cp = rq_ctxmap[uptr->cnum]; t_stat r; @@ -2132,10 +2256,10 @@ t_stat rq_detach (UNIT *uptr) { t_stat r; -r = detach_unit (uptr); /* detach unit */ +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 */ +uptr->flags = uptr->flags & ~(UNIT_ONL | UNIT_ATP); /* clr onl, atn pend */ +uptr->uf = 0; /* clr unit flgs */ return SCPE_OK; } @@ -2148,126 +2272,129 @@ 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 */ +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 */ -#if defined (VM_VAX) /* VAX */ -cp->ubase = 0; /* unit base = 0 */ -#else /* PDP-11 */ -cp->ubase = cidx * RQ_NUMDR; /* init unit base */ +#if defined (VM_VAX) /* VAX */ +cp->ubase = 0; /* unit base = 0 */ +#else /* PDP-11 */ +cp->ubase = cidx * RQ_NUMDR; /* init unit base */ #endif -cp->csta = CST_S1; /* init stage 1 */ -cp->s1dat = 0; /* no S1 data */ -dibp->vec = 0; /* no vector */ -cp->comm = 0; /* no comm region */ -if (UNIBUS) cp->sa = SA_S1 | SA_S1C_DI | SA_S1C_MP; /* Unibus? */ +cp->csta = CST_S1; /* init stage 1 */ +cp->s1dat = 0; /* no S1 data */ +dibp->vec = 0; /* no vector */ +cp->comm = 0; /* no comm region */ +if (UNIBUS) cp->sa = SA_S1 | SA_S1C_DI | SA_S1C_MP; /* Unibus? */ else 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 (uint16)); +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 = (uint16 *) calloc (RQ_MAXFR >> 1, sizeof (uint16)); if (rqxb == NULL) return SCPE_MEM; -return auto_config (0, 0); /* run autoconfig */ +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)) +#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" */ + 0042125, /* st: "UD" */ - /* Four step init process */ + /* 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? */ + 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 */ + /* 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 */ + 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 */ + /* 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 */ + 0005011, /* done: clr (r1) ; for M+ */ + 0005003, /* clr r3 */ + 0012704, BOOT_START+020, /* mov #st+020,r4 */ + 0005005, /* clr r5 */ + 0005007, /* clr pc */ - /* Data */ + /* 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 -}; + 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) { @@ -2290,7 +2417,7 @@ 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) @@ -2300,22 +2427,23 @@ 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); + 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); + 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)) { - fprintf (st, " %3d: non-existent memory\n", i); - break; } - desc = ((uint32) d[0]) | (((uint32) d[1]) << 16); + if (Map_ReadW (rp->ba + (i << 2), 4, d)) { + 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); + fprintf (st, " %3d: %011o\n", i, desc); #else - fprintf (st, " %3d: %08x\n", i, desc); + fprintf (st, " %3d: %08x\n", i, desc); #endif - } + } return; } @@ -2327,17 +2455,17 @@ 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); + 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++) + 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]); + fprintf (st, " %06o", cp->pak[pkt].d[j]); #else - fprintf (st, " %04x", cp->pak[pkt].d[j]); + fprintf (st, " %04x", cp->pak[pkt].d[j]); #endif - fprintf (st, "\n"); - } + fprintf (st, "\n"); + } return; } @@ -2347,22 +2475,27 @@ MSC *cp = rq_ctxmap[uptr->cnum]; DEVICE *dptr = rq_devmap[uptr->cnum]; int32 pkt, u; -u = uptr - dptr->units; +u = (int32) (uptr - dptr->units); if (cp->csta != CST_UP) { - fprintf (st, "Controller is not initialized\n"); - return SCPE_OK; } + 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->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); } } + 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; } @@ -2375,7 +2508,8 @@ int32 i, pkt; if (cp->csta != CST_UP) { fprintf (st, "Controller is not initialized\n"); - return SCPE_OK; } + 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); @@ -2386,23 +2520,27 @@ if (val & RQ_SH_RI) { } 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"); } + 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); } + 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); + rq_show_unitq (st, dptr->units + i, 0, desc); } return SCPE_OK; } diff --git a/PDP11/pdp11_rx.c b/PDP11/pdp11_rx.c index 5cf836ab..78cff3d2 100644 --- a/PDP11/pdp11_rx.c +++ b/PDP11/pdp11_rx.c @@ -1,6 +1,6 @@ /* pdp11_rx.c: RX11/RX01 floppy disk simulator - Copyright (c) 1993-2004, Robert M Supnik + Copyright (c) 1993-2005, 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"), @@ -19,28 +19,29 @@ 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 + 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 + 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 + 07-Jul-05 RMS Removed extraneous externs + 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. @@ -48,81 +49,80 @@ #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 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 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 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 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 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 */ -int32 rx_bptr = 0; /* buffer pointer */ -int32 rx_enb = 1; /* device enable */ +extern int32 int_req[IPL_HLVL]; + +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 */ +int32 rx_bptr = 0; /* buffer pointer */ +int32 rx_enb = 1; /* device enable */ DEVICE rx_dev; t_stat rx_rd (int32 *data, int32 PA, int32 access); @@ -134,164 +134,184 @@ 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 + 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 } }; +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) } }; + { 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, rx_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 } }; + { 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, rx_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 } }; + { 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 }; - + "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 + 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 */ +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> */ +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 + - 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 */ - rx_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 */ - + 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 */ + rx_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 */ + 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[rx_bptr], advance ptr - if rx_bptr > max, finish command, else set tr - EMPTY if rx_bptr > max, finish command, else - copy rx_buf[rx_bptr] to ir, advance ptr, set tr - CMD_COMPLETE copy requested data to ir, finish command + 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[rx_bptr], advance ptr + if rx_bptr > max, finish command, else set tr + EMPTY if rx_bptr > max, finish command, else + copy rx_buf[rx_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; @@ -304,87 +324,100 @@ int32 i, func; uint32 da; int8 *fbuf = uptr->filebuf; -func = RXCS_GETFNC (rx_csr); /* get function */ -switch (rx_state) { /* case on state */ +func = RXCS_GETFNC (rx_csr); /* get function */ +switch (rx_state) { /* case on state */ -case IDLE: /* idle */ - return SCPE_IERR; /* done */ + case IDLE: /* idle */ + return SCPE_IERR; /* done */ -case EMPTY: /* empty buffer */ - if (rx_bptr >= RX_NUMBY) rx_done (0, 0); /* done all? */ - else { - rx_dbr = rx_buf[rx_bptr]; /* get next */ - rx_bptr = rx_bptr + 1; - rx_csr = rx_csr | RXCS_TR; } /* set xfer */ - break; + case EMPTY: /* empty buffer */ + if (rx_bptr >= RX_NUMBY) rx_done (0, 0); /* done all? */ + else { + rx_dbr = rx_buf[rx_bptr]; /* get next */ + rx_bptr = rx_bptr + 1; + rx_csr = rx_csr | RXCS_TR; /* set xfer */ + } + break; -case FILL: /* fill buffer */ - rx_buf[rx_bptr] = rx_dbr; /* write next */ - rx_bptr = rx_bptr + 1; - if (rx_bptr < RX_NUMBY) rx_csr = rx_csr | RXCS_TR; /* more? set xfer */ - else rx_done (0, 0); /* else done */ - break; + case FILL: /* fill buffer */ + rx_buf[rx_bptr] = rx_dbr; /* write next */ + rx_bptr = rx_bptr + 1; + if (rx_bptr < RX_NUMBY) rx_csr = rx_csr | RXCS_TR; /* 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] = fbuf[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 */ - fbuf[da + i] = rx_buf[i]; - da = da + RX_NUMBY; - if (da > uptr->hwmark) uptr->hwmark = da; } - rx_done (0, 0); /* 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 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 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] = fbuf[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 */ + fbuf[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] = fbuf[da + i]; + rx_done (RXES_ID, 0); /* set done */ + if ((rx_unit[1].flags & UNIT_ATT) == 0) rx_ecode = 0020; + break; + } /* end case state */ -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] = fbuf[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. */ @@ -393,16 +426,16 @@ 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_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 */ + 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; } @@ -412,63 +445,64 @@ return; 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 */ +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)) +#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 */ -}; + 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) { diff --git a/PDP11/pdp11_ry.c b/PDP11/pdp11_ry.c index 897f5927..359dbb31 100644 --- a/PDP11/pdp11_ry.c +++ b/PDP11/pdp11_ry.c @@ -19,142 +19,140 @@ 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 + 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 RX211/RXV21/RX02 floppy disk + ry RX211/RXV21/RX02 floppy disk - 18-Feb-05 RMS Fixed bug in boot code (reported by Graham Toal) - 30-Sep-04 RMS Revised Unibus interface - 21-Mar-04 RMS Added VAX support - 29-Dec-03 RMS Added RXV21 support - 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 + 07-Jul-05 RMS Removed extraneous externs + 18-Feb-05 RMS Fixed bug in boot code (reported by Graham Toal) + 30-Sep-04 RMS Revised Unibus interface + 21-Mar-04 RMS Added VAX support + 29-Dec-03 RMS Added RXV21 support + 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 */ +#if defined (VM_PDP10) /* PDP10 version */ #include "pdp10_defs.h" extern int32 int_req; -extern int32 int_vec[32]; -#define DEV_DISI DEV_DIS +#define DEV_DISI DEV_DIS -#elif defined (VM_VAX) /* VAX version */ +#elif defined (VM_VAX) /* VAX version */ #include "vax_defs.h" extern int32 int_req[IPL_HLVL]; -extern int32 int_vec[IPL_HLVL][32]; -#define DEV_DISI 0 +#define DEV_DISI 0 -#else /* PDP-11 version */ +#else /* PDP-11 version */ #include "pdp11_defs.h" extern int32 int_req[IPL_HLVL]; -extern int32 int_vec[IPL_HLVL][32]; -#define DEV_DISI DEV_DIS +#define DEV_DISI DEV_DIS #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 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 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 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 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 */ +#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 */ DEVICE ry_dev; t_stat ry_rd (int32 *data, int32 PA, int32 access); @@ -168,179 +166,199 @@ 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 + 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 } }; +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) } }; + { 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[] = { - { GRDATA (RYCS, ry_csr, DEV_RDX, 16, 0) }, - { GRDATA (RYBA, ry_ba, DEV_RDX, 16, 0) }, - { GRDATA (RYWC, ry_wc, DEV_RDX, 8, 0) }, - { GRDATA (RYDB, ry_dbr, DEV_RDX, 16, 0) }, - { GRDATA (RYES, ry_esr, DEV_RDX, 12, 0) }, - { GRDATA (RYERR, ry_ecode, DEV_RDX, 8, 0) }, - { GRDATA (RYTA, ry_track, DEV_RDX, 8, 0) }, - { GRDATA (RYSA, ry_sector, DEV_RDX, 8, 0) }, - { 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) }, - { GRDATA (DEVADDR, ry_dib.ba, DEV_RDX, 32, 0), REG_HRO }, - { GRDATA (DEVVEC, ry_dib.vec, DEV_RDX, 16, 0), REG_HRO }, - { NULL } }; + { GRDATA (RYCS, ry_csr, DEV_RDX, 16, 0) }, + { GRDATA (RYBA, ry_ba, DEV_RDX, 16, 0) }, + { GRDATA (RYWC, ry_wc, DEV_RDX, 8, 0) }, + { GRDATA (RYDB, ry_dbr, DEV_RDX, 16, 0) }, + { GRDATA (RYES, ry_esr, DEV_RDX, 12, 0) }, + { GRDATA (RYERR, ry_ecode, DEV_RDX, 8, 0) }, + { GRDATA (RYTA, ry_track, DEV_RDX, 8, 0) }, + { GRDATA (RYSA, ry_sector, DEV_RDX, 8, 0) }, + { 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) }, + { GRDATA (DEVADDR, ry_dib.ba, DEV_RDX, 32, 0), REG_HRO }, + { GRDATA (DEVVEC, ry_dib.vec, DEV_RDX, 16, 0), 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 }, + { 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 }, + { MTAB_XTD | MTAB_VDV, 0, NULL, "AUTOCONFIGURE", + &set_addr_flt, NULL, NULL }, #endif - { 0 } }; + { 0 } + }; DEVICE ry_dev = { - "RY", ry_unit, ry_reg, ry_mod, - RX_NUMDR, DEV_RDX, 20, 1, DEV_RDX, 8, - NULL, NULL, &ry_reset, - &ry_boot, &ry_attach, NULL, - &ry_dib, DEV_FLTA | DEV_DISABLE | DEV_DISI | DEV_UBUS | DEV_Q18 }; - + "RY", ry_unit, ry_reg, ry_mod, + RX_NUMDR, DEV_RDX, 20, 1, DEV_RDX, 8, + NULL, NULL, &ry_reset, + &ry_boot, &ry_attach, NULL, + &ry_dib, DEV_FLTA | DEV_DISABLE | DEV_DISI | DEV_UBUS | DEV_Q18 + }; + /* I/O dispatch routine, I/O addresses 17777170 - 17777172 - 17777170 floppy CSR - 17777172 floppy data register + 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 */ +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> */ +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 + - 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 */ + 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 */ + 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 + 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 */ @@ -351,133 +369,154 @@ static uint8 estat[8]; uint32 ba, da; int8 *fbuf = uptr->filebuf; -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 */ +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); } - else t = Map_WriteB (ba, ry_wc << 1, rx2xb); - ry_wc = t >> 1; /* adjust wc */ - ry_done (t? RYES_NXM: 0, 0); /* done */ - break; + case IDLE: /* idle */ + return SCPE_IERR; -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] = fbuf[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 */ - fbuf[da + i] = rx2xb[i]; - da = da + bps; - if (da > uptr->hwmark) uptr->hwmark = da; } - ry_done (0, 0); /* done */ - break; + 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 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++) fbuf[i] = 0; - uptr->hwmark = (uint32) 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 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 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); /* DMA to memory */ - ry_done (t? RYES_NXM: 0, 0); /* done */ - break; + 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); + } + else t = Map_WriteB (ba, ry_wc << 1, rx2xb); + ry_wc = t >> 1; /* adjust wc */ + ry_done (t? RYES_NXM: 0, 0); /* done */ + break; -case CMD_COMPLETE: /* command complete */ - ry_done (0, 0); - 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 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] = fbuf[da + i]; - ry_done (RYES_ID, 0); /* set done */ - if ((ry_unit[1].flags & UNIT_ATT) == 0) ry_ecode = 0020; - break; } /* end case state */ + 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] = fbuf[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 */ + fbuf[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++) fbuf[i] = 0; + uptr->hwmark = (uint32) 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); /* 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] = fbuf[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. */ @@ -486,19 +525,20 @@ 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_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 (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 */ + 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; } @@ -508,19 +548,20 @@ return; 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 */ +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 */ @@ -533,8 +574,9 @@ t_stat r; r = attach_unit (uptr, cptr); if (r != SCPE_OK) return r; if ((uptr->flags & UNIT_AUTO) && (sz = sim_fsize (uptr->fileref))) { - if (sz > RX_SIZE) uptr->flags = uptr->flags | UNIT_DEN; - else uptr->flags = uptr->flags & ~UNIT_DEN; } + 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 SCPE_OK; } @@ -547,77 +589,77 @@ 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)) +#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) */ - 0050316, /* BIS R3, (SP) ; or unit */ - 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? */ - 0001345, /* 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? */ - 0101715, /* BLOS RD ; read next */ - 0005002, /* CLR R2 */ - 0005003, /* CLR R3 */ - 0012704, BOOT_START+020, /* MOV #START+20, R4 */ - 0005005, /* CLR R5 */ - 0005007 /* CLR R7 */ -}; + 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) */ + 0050316, /* BIS R3, (SP) ; or unit */ + 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? */ + 0001345, /* 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? */ + 0101715, /* 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) { @@ -626,7 +668,7 @@ extern int32 saved_PC; extern uint16 *M; if ((ry_unit[unitno & RX_M_NUMDR].flags & UNIT_DEN) == 0) - return SCPE_NOFNC; + 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; diff --git a/PDP11/pdp11_stddev.c b/PDP11/pdp11_stddev.c index 326cc67f..982d19b8 100644 --- a/PDP11/pdp11_stddev.c +++ b/PDP11/pdp11_stddev.c @@ -1,6 +1,6 @@ /* pdp11_stddev.c: PDP-11 standard I/O devices simulator - Copyright (c) 1993-2004, Robert M Supnik + Copyright (c) 1993-2005, 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"), @@ -19,64 +19,64 @@ 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 + 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 (and other) line frequency clock + tti,tto DL11 terminal input/output + clk KW11L (and other) line frequency clock - 11-Oct-04 RMS Added clock model dependencies - 28-May-04 RMS Removed SET TTI CTRL-C - 29-Dec-03 RMS Added console backpressure support - 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 + 07-Jul-05 RMS Removed extraneous externs + 11-Oct-04 RMS Added clock model dependencies + 28-May-04 RMS Removed SET TTI CTRL-C + 29-Dec-03 RMS Added console backpressure support + 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 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) +#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]; extern int32 cpu_type; -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 clk_default = 60; /* default ticks/second */ -int32 clk_fie = 0; /* force IE = 1 */ -int32 clk_fnxm = 0; /* force NXM on reg */ -int32 tmxr_poll = CLK_DELAY; /* term mux poll */ -int32 tmr_poll = CLK_DELAY; /* timer poll */ +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 clk_default = 60; /* default ticks/second */ +int32 clk_fie = 0; /* force IE = 1 */ +int32 clk_fnxm = 0; /* force NXM on reg */ +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); @@ -94,157 +94,180 @@ int32 clk_inta (void); 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 + 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 } }; +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 } }; + { 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, 0, "ADDRESS", NULL, - NULL, &show_addr, NULL }, - { MTAB_XTD|MTAB_VDV, 0, "VECTOR", NULL, - NULL, &show_vec, NULL }, - { 0 } }; + { 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 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 }; + "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 + 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 } }; +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 } }; + { 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 } }; + { 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 }; - + "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 + 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, { &clk_inta } }; +DIB clk_dib = { + IOBA_CLK, IOLN_CLK, &clk_rd, &clk_wr, + 1, IVCL (CLK), VEC_CLK, { &clk_inta } + }; 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, 16), PV_LEFT + REG_HRO }, - { DRDATA (DEFTPS, clk_default, 16), PV_LEFT + REG_HRO }, - { FLDATA (FIE, clk_fie, 0), REG_HIDDEN }, - { FLDATA (FNXM, clk_fnxm, 0), REG_HIDDEN }, - { NULL } }; + { 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, 16), PV_LEFT + REG_HRO }, + { DRDATA (DEFTPS, clk_default, 16), PV_LEFT + REG_HRO }, + { FLDATA (FIE, clk_fie, 0), REG_HIDDEN }, + { FLDATA (FNXM, clk_fnxm, 0), REG_HIDDEN }, + { 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 } }; + { 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 }; - + "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 */ +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 */ +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; } @@ -254,9 +277,9 @@ 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? */ +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; @@ -271,40 +294,48 @@ 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 */ +sim_activate (&tti_unit, tti_unit.wait); /* activate unit */ 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 */ +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 */ +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; } @@ -316,9 +347,10 @@ int32 c; t_stat r; c = tto_unit.buf & ((tto_unit.flags & UNIT_8B)? 0377: 0177); -if ((r = sim_putchar_s (c)) != SCPE_OK) { /* output; error? */ - sim_activate (uptr, uptr->wait); /* try again */ - return ((r == SCPE_STALL)? SCPE_OK: r); } /* !stall? report */ +if ((r = sim_putchar_s (c)) != SCPE_OK) { /* output; error? */ + sim_activate (uptr, uptr->wait); /* try again */ + return ((r == SCPE_STALL)? SCPE_OK: r); /* !stall? report */ + } tto_csr = tto_csr | CSR_DONE; if (tto_csr & CSR_IE) SET_INT (TTO); tto_unit.pos = tto_unit.pos + 1; @@ -332,7 +364,7 @@ t_stat tto_reset (DEVICE *dptr) tto_unit.buf = 0; tto_csr = CSR_DONE; CLR_INT (TTO); -sim_cancel (&tto_unit); /* deactivate unit */ +sim_cancel (&tto_unit); /* deactivate unit */ return SCPE_OK; } @@ -342,34 +374,34 @@ tti_unit.flags = (tti_unit.flags & ~UNIT_8B) | val; tto_unit.flags = (tto_unit.flags & ~UNIT_8B) | val; return SCPE_OK; } - + /* The line time clock has a few twists and turns through the history of 11's - LSI-11 no CSR - LSI-11/23 (KDF11A) no CSR - PDP-11/23+ (KDF11B) no monitor bit - PDP-11/24 (KDF11U) monitor bit clears on IAK + LSI-11 no CSR + LSI-11/23 (KDF11A) no CSR + PDP-11/23+ (KDF11B) no monitor bit + PDP-11/24 (KDF11U) monitor bit clears on IAK */ /* Clock I/O address routines */ t_stat clk_rd (int32 *data, int32 PA, int32 access) { -if (clk_fnxm) return SCPE_NXM; /* not there??? */ -if (CPUT (HAS_LTCM)) *data = clk_csr & CLKCSR_IMP; /* monitor bit? */ -else *data = clk_csr & (CLKCSR_IMP & ~CSR_DONE); /* no, just IE */ +if (clk_fnxm) return SCPE_NXM; /* not there??? */ +if (CPUT (HAS_LTCM)) *data = clk_csr & CLKCSR_IMP; /* monitor bit? */ +else *data = clk_csr & (CLKCSR_IMP & ~CSR_DONE); /* no, just IE */ return SCPE_OK; } t_stat clk_wr (int32 data, int32 PA, int32 access) { -if (clk_fnxm) return SCPE_NXM; /* not there??? */ +if (clk_fnxm) return SCPE_NXM; /* not there??? */ if (PA & 1) return SCPE_OK; clk_csr = (clk_csr & ~CLKCSR_RW) | (data & CLKCSR_RW); -if (CPUT (HAS_LTCM) && ((data & CSR_DONE) == 0)) /* monitor bit? */ - clk_csr = clk_csr & ~CSR_DONE; /* clr if zero */ -if ((((clk_csr & CSR_IE) == 0) && !clk_fie) || /* unless IE+DONE */ - ((clk_csr & CSR_DONE) == 0)) CLR_INT (CLK); /* clr intr */ +if (CPUT (HAS_LTCM) && ((data & CSR_DONE) == 0)) /* monitor bit? */ + clk_csr = clk_csr & ~CSR_DONE; /* clr if zero */ +if ((((clk_csr & CSR_IE) == 0) && !clk_fie) || /* unless IE+DONE */ + ((clk_csr & CSR_DONE) == 0)) CLR_INT (CLK); /* clr intr */ return SCPE_OK; } @@ -379,12 +411,12 @@ t_stat clk_svc (UNIT *uptr) { int32 t; -clk_csr = clk_csr | CSR_DONE; /* set done */ +clk_csr = clk_csr | CSR_DONE; /* set done */ if ((clk_csr & CSR_IE) || clk_fie) 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 */ +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; } @@ -400,14 +432,14 @@ return clk_dib.vec; t_stat clk_reset (DEVICE *dptr) { -if (CPUT (HAS_LTCR)) clk_fie = clk_fnxm = 0; /* reg there? */ -else clk_fie = clk_fnxm = 1; /* no, BEVENT */ -clk_tps = clk_default; /* set default tps */ -clk_csr = CSR_DONE; /* set done */ +if (CPUT (HAS_LTCR)) clk_fie = clk_fnxm = 0; /* reg there? */ +else clk_fie = clk_fnxm = 1; /* no, BEVENT */ +clk_tps = clk_default; /* set default tps */ +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 */ +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; } diff --git a/PDP11/pdp11_sys.c b/PDP11/pdp11_sys.c index 7bd652e6..2cfb9456 100644 --- a/PDP11/pdp11_sys.c +++ b/PDP11/pdp11_sys.c @@ -1,6 +1,6 @@ /* pdp11_sys.c: PDP-11 simulator interface - Copyright (c) 1993-2004, Robert M Supnik + Copyright (c) 1993-2005, 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"), @@ -19,33 +19,35 @@ 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 + 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-03 RMS Added second DEUNA/DELUA support - 18-Oct-03 RMS Added DECtape off reel message - 06-May-03 RMS Added support for second DEQNA/DELQA - 09-Jan-03 RMS Added DELUA/DEUNA 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 + 16-Aug-05 RMS Fixed C++ declaration and cast problems + 22-Jul-05 RMS Fixed missing , in initializer (from Doug Gwyn) + 22-Dec-03 RMS Added second DEUNA/DELUA support + 18-Oct-03 RMS Added DECtape off reel message + 06-May-03 RMS Added support for second DEQNA/DELQA + 09-Jan-03 RMS Added DELUA/DEUNA 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" @@ -76,12 +78,12 @@ 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 + 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"; @@ -91,81 +93,83 @@ REG *sim_PC = &cpu_reg[0]; int32 sim_emax = 4; DEVICE *sim_devices[] = { - &cpu_dev, - &sys_dev, - &mba0_dev, - &mba1_dev, - &ptr_dev, - &ptp_dev, - &tti_dev, - &tto_dev, - &lpt_dev, - &clk_dev, - &pclk_dev, - &dz_dev, - &vh_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, - &tu_dev, - &xq_dev, - &xqb_dev, - &xu_dev, - &xub_dev, - NULL }; + &cpu_dev, + &sys_dev, + &mba0_dev, + &mba1_dev, + &ptr_dev, + &ptp_dev, + &tti_dev, + &tto_dev, + &lpt_dev, + &clk_dev, + &pclk_dev, + &dz_dev, + &vh_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, + &tu_dev, + &xq_dev, + &xqb_dev, + &xu_dev, + &xub_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" - "DECtape off reel" }; - + "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", + "DECtape off reel" + }; + /* 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 + 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 @@ -180,75 +184,85 @@ 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 */ + 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) + 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 + uptr = pointer to unit + sec = number of sectors per surface + wds = number of words per sector Outputs: - sta = status code + sta = status code */ t_stat pdp11_bad_block (UNIT *uptr, int32 sec, int32 wds) { int32 i, da; -int16 *buf; +uint16 *buf; if ((sec < 2) || (wds < 16)) return SCPE_ARG; if ((uptr->flags & UNIT_ATT) == 0) return SCPE_UNATT; @@ -256,66 +270,67 @@ 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; +if ((buf = (uint16 *) malloc (wds * sizeof (uint16))) == 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); + fxwrite (buf, sizeof (uint16), 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) +#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) +#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 }; +0177400+I_D+I_L, 0170000, 0177777, 0177777 +}; static const char *opcode[] = { "HALT","WAIT","RTI","BPT", @@ -361,7 +376,7 @@ static const char *opcode[] = { "SOB", "BPL","BMI","BHI","BLOS", "BVC","BVS","BCC","BCS", -"BHIS","BLO", /* encode only */ +"BHIS","BLO", /* encode only */ "EMT","TRAP", "CLRB","COMB","INCB","DECB", "NEGB","ADCB","SBCB","TSTB", @@ -383,7 +398,8 @@ static const char *opcode[] = { "LDEXP", "LDCIF","LDCID","LDCLF","LDCLD", "LDCFD","LDCDF", -NULL }; +NULL +}; static const int32 opc_val[] = { 0000000+I_NPN, 0000001+I_NPN, 0000002+I_NPN, 0000003+I_NPN, @@ -451,31 +467,34 @@ static const int32 opc_val[] = { 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 }; +-1 +}; -static const char *rname [] = -{ "R0", "R1", "R2", "R3", "R4", "R5", "SP", "PC" }; +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 *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 + *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 + count = -number of extra words retired */ int32 fprint_spec (FILE *of, t_addr addr, int32 spec, t_value nval, - int32 flag, int32 iflag) + int32 flag, int32 iflag) { int32 reg, mode; static const int32 rgwd[8] = { 0, 0, 0, 0, 0, 0, -1, -1 }; @@ -484,179 +503,203 @@ 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 */ + + 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 + *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 + 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) + 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); -if (sw & SWMASK ('A')) { /* ASCII? */ - c1 = (val[0] >> ((addr & 1)? 8: 0)) & 0177; - fprintf (of, (c1 < 040)? "<%03o>": "%c", c1); - return 0; } -if (sw & SWMASK ('B')) { /* byte? */ - c1 = (val[0] >> ((addr & 1)? 8: 0)) & 0377; - fprintf (of, "%o", c1); - return 0; } -if (sw & SWMASK ('C')) { /* character? */ - c1 = val[0] & 0177; - c2 = (val[0] >> 8) & 0177; - fprintf (of, (c1 < 040)? "<%03o>": "%c", c1); - fprintf (of, (c2 < 040)? "<%03o>": "%c", c2); - return -1; } -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 -1; } +if (sw & SWMASK ('A')) { /* ASCII? */ + c1 = (val[0] >> ((addr & 1)? 8: 0)) & 0177; + fprintf (of, (c1 < 040)? "<%03o>": "%c", c1); + return 0; + } +if (sw & SWMASK ('B')) { /* byte? */ + c1 = (val[0] >> ((addr & 1)? 8: 0)) & 0377; + fprintf (of, "%o", c1); + return 0; + } +if (sw & SWMASK ('C')) { /* character? */ + c1 = val[0] & 0177; + c2 = (val[0] >> 8) & 0177; + fprintf (of, (c1 < 040)? "<%03o>": "%c", c1); + fprintf (of, (c2 < 040)? "<%03o>": "%c", c2); + return -1; + } +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 -1; + } 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; - wd1 = wd2 = 0; - -/* Instruction decode */ + ((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; + wd1 = wd2 = 0; + switch (j) { /* case on class */ - switch (j) { /* case on class */ - case I_V_NPN: case I_V_CCC: case I_V_CCS: /* no operands */ - fprintf (of, "%s", opcode[i]); - break; - case I_V_REG: /* reg */ - fprintf (of, "%s %-s", opcode[i], rname[dstr]); - break; - case I_V_SOP: /* sop */ - fprintf (of, "%s ", opcode[i]); - wd1 = fprint_spec (of, addr, dstm, val[1], cflag, TRUE); - break; - case I_V_3B: /* 3b */ - fprintf (of, "%s %-o", opcode[i], dstr); - break; - case I_V_FOP: /* fop */ - fprintf (of, "%s ", opcode[i]); - wd1 = fprint_spec (of, addr, dstm, val[1], cflag, FALSE); - break; - case I_V_AFOP: /* afop */ - fprintf (of, "%s %s,", opcode[i], fname[fac]); - wd1 = fprint_spec (of, addr, dstm, val[1], cflag, FALSE); - break; - case I_V_6B: /* 6b */ - fprintf (of, "%s %-o", opcode[i], dstm); - break; - 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); - break; - case I_V_8B: /* 8b */ - fprintf (of, "%s %-o", opcode[i], l8b); - break; - 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); - break; - case I_V_RSOP: /* rsop */ - fprintf (of, "%s %s,", opcode[i], rname[srcr]); - wd1 = fprint_spec (of, addr, dstm, val[1], cflag, TRUE); - break; - case I_V_ASOP: case I_V_ASMD: /* asop, asmd */ - fprintf (of, "%s %s,", opcode[i], fname[fac]); - wd1 = fprint_spec (of, addr, dstm, val[1], cflag, TRUE); - break; - 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); - break; - } /* end case */ - return ((wd1 + wd2) * 2) - 1; - } /* end if */ - } /* end for */ -return SCPE_ARG; /* no match */ + case I_V_NPN: case I_V_CCC: case I_V_CCS: /* no operands */ + fprintf (of, "%s", opcode[i]); + break; + + case I_V_REG: /* reg */ + fprintf (of, "%s %-s", opcode[i], rname[dstr]); + break; + + case I_V_SOP: /* sop */ + fprintf (of, "%s ", opcode[i]); + wd1 = fprint_spec (of, addr, dstm, val[1], cflag, TRUE); + break; + + case I_V_3B: /* 3b */ + fprintf (of, "%s %-o", opcode[i], dstr); + break; + + case I_V_FOP: /* fop */ + fprintf (of, "%s ", opcode[i]); + wd1 = fprint_spec (of, addr, dstm, val[1], cflag, FALSE); + break; + + case I_V_AFOP: /* afop */ + fprintf (of, "%s %s,", opcode[i], fname[fac]); + wd1 = fprint_spec (of, addr, dstm, val[1], cflag, FALSE); + break; + + case I_V_6B: /* 6b */ + fprintf (of, "%s %-o", opcode[i], dstm); + break; + + 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); + break; + + case I_V_8B: /* 8b */ + fprintf (of, "%s %-o", opcode[i], l8b); + break; + + 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); + break; + + case I_V_RSOP: /* rsop */ + fprintf (of, "%s %s,", opcode[i], rname[srcr]); + wd1 = fprint_spec (of, addr, dstm, val[1], cflag, TRUE); + break; + + case I_V_ASOP: case I_V_ASMD: /* asop, asmd */ + fprintf (of, "%s %s,", opcode[i], fname[fac]); + wd1 = fprint_spec (of, addr, dstm, val[1], cflag, TRUE); + break; + + 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); + break; + } /* end case */ + return ((wd1 + wd2) * 2) - 1; + } /* 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 */ + +#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 + *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 + rnum = 0..7 if a legitimate register + < 0 if error */ int32 get_reg (char *cptr, const char *strings[], char mchar) @@ -665,19 +708,20 @@ int32 i; if (*(cptr + 2) != mchar) return -1; for (i = 0; i < 8; i++) { - if (strncmp (cptr, strings[i], 2) == 0) return 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 + *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 + cptr = pointer to next character in input string + NULL if parsing error Flags: 0 (no result), A_NUM (number), A_REL (relative) */ @@ -689,132 +733,153 @@ 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++; } +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? */ +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 + *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 + 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 cflag, int32 iflag) { int32 reg, indir, pflag, disp; -indir = 0; /* no indirect */ +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++; } +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++; } } +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 */ + pflag = pflag | A_REG; + cptr = cptr + 2; + } +if (*cptr != 0) return 1; /* all done? */ +switch (pflag) { /* case on syntax */ -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 */ + 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 + *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 + 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) @@ -825,110 +890,128 @@ t_stat r; char *tptr, gbuf[CBUFSIZE]; cflag = (uptr == NULL) || (uptr == &cpu_unit); -while (isspace (*cptr)) cptr++; /* absorb spaces */ +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 */ - if (addr & 1) val[0] = (val[0] & 0377) | (((t_value) cptr[0]) << 8); - else val[0] = (val[0] & ~0377) | ((t_value) cptr[0]); - return 0; } -if (sw & SWMASK ('B')) { /* byte? */ - by = get_uint (cptr, 8, 0377, &r); /* get byte */ - if (r != SCPE_OK) return SCPE_ARG; - if (addr & 1) val[0] = (val[0] & 0377) | (by << 8); - else val[0] = (val[0] & ~0377) | by; - return 0; } + if (cptr[0] == 0) return SCPE_ARG; /* must have 1 char */ + if (addr & 1) val[0] = (val[0] & 0377) | (((t_value) cptr[0]) << 8); + else val[0] = (val[0] & ~0377) | ((t_value) cptr[0]); + return 0; + } +if (sw & SWMASK ('B')) { /* byte? */ + by = get_uint (cptr, 8, 0377, &r); /* get byte */ + if (r != SCPE_OK) return SCPE_ARG; + if (addr & 1) val[0] = (val[0] & 0377) | (by << 8); + else val[0] = (val[0] & ~0377) | by; + return 0; + } 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 -1; } -if (sw & SWMASK ('R')) return SCPE_ARG; /* radix 50 */ + if (cptr[0] == 0) return SCPE_ARG; /* must have 1 char */ + val[0] = ((t_value) cptr[1] << 8) | (t_value) cptr[0]; + return -1; + } +if (sw & SWMASK ('R')) return SCPE_ARG; /* radix 50 */ -cptr = get_glyph (cptr, gbuf, 0); /* get opcode */ +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 */ +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? */ +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) * 2) - 1; } diff --git a/PDP11/pdp11_tc.c b/PDP11/pdp11_tc.c index 52cdb319..fd9d8476 100644 --- a/PDP11/pdp11_tc.c +++ b/PDP11/pdp11_tc.c @@ -1,6 +1,6 @@ /* pdp11_tc.c: PDP-11 DECtape simulator - Copyright (c) 1993-2004, Robert M Supnik + Copyright (c) 1993-2005, 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"), @@ -19,48 +19,50 @@ 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 + 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 + tc TC11/TU56 DECtape - 30-Sep-04 RMS Revised Unibus interface - 25-Jan-04 RMS Revised for device debug support - 09-Jan-04 RMS Changed sim_fsize calling sequence, added STOP_OFFR - 29-Dec-03 RMS Changed initial status to disabled (in Qbus system) - 18-Oct-03 RMS Fixed reverse checksum in read all - Added DECtape off reel message - Simplified timing - 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 + 16-Aug-05 RMS Fixed C++ declaration and cast problems + 07-Jul-05 RMS Removed extraneous externs + 30-Sep-04 RMS Revised Unibus interface + 25-Jan-04 RMS Revised for device debug support + 09-Jan-04 RMS Changed sim_fsize calling sequence, added STOP_OFFR + 29-Dec-03 RMS Changed initial status to disabled (in Qbus system) + 18-Oct-03 RMS Fixed reverse checksum in read all + Added DECtape off reel message + Simplified timing + 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] + 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. @@ -68,13 +70,13 @@ Tape density is nominally 300 lines per inch. The format of a DECtape (as taken from the TD8E formatter) is: - reverse end zone 8192 reverse end zone codes ~ 10 feet - reverse buffer 200 interblock codes - block 0 - : - block n - forward buffer 200 interblock codes - forward end zone 8192 forward end zone codes ~ 10 feet + reverse end zone 8192 reverse end zone codes ~ 10 feet + reverse buffer 200 interblock codes + block 0 + : + block n + forward buffer 200 interblock codes + forward end zone 8192 forward end zone codes ~ 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 @@ -86,15 +88,15 @@ 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 checksum (for reverse reads) - : - trailer word 4 checksum (for forward reads) - trailer words 3,2 0 - trailer word 1 block number (for reverse reads) - trailer word 0 0 + header word 0 0 + header word 1 block number (for forward reads) + header words 2,3 0 + header word 4 checksum (for reverse reads) + : + trailer word 4 checksum (for forward reads) + 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. @@ -102,124 +104,124 @@ #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 */ +#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_LPERMC 6 /* lines per mark track */ -#define DT_BLKWD 1 /* blk no word in h/t */ -#define DT_CSMWD 4 /* checksum word in h/t */ -#define DT_HTWRD 5 /* header/trailer words */ -#define DT_EZLIN (8192 * DT_LPERMC) /* end zone length */ -#define DT_BFLIN (200 * DT_LPERMC) /* buffer length */ -#define DT_BLKLN (DT_BLKWD * DT_LPERMC) /* blk no line in h/t */ -#define DT_CSMLN (DT_CSMWD * DT_LPERMC) /* csum line in h/t */ -#define DT_HTLIN (DT_HTWRD * DT_LPERMC) /* header/trailer lines */ +#define DT_LPERMC 6 /* lines per mark track */ +#define DT_BLKWD 1 /* blk no word in h/t */ +#define DT_CSMWD 4 /* checksum word in h/t */ +#define DT_HTWRD 5 /* header/trailer words */ +#define DT_EZLIN (8192 * DT_LPERMC) /* end zone length */ +#define DT_BFLIN (200 * DT_LPERMC) /* buffer length */ +#define DT_BLKLN (DT_BLKWD * DT_LPERMC) /* blk no line in h/t */ +#define DT_CSMLN (DT_CSMWD * DT_LPERMC) /* csum line in h/t */ +#define DT_HTLIN (DT_HTWRD * DT_LPERMC) /* header/trailer lines */ /* 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)) +#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_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)) +#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 +#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 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)) +#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) +#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_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)) +#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 */ @@ -229,58 +231,57 @@ /* 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_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) + ((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) + ((DTS_STA (y, z)) << DTS_V_3RD) +#define DTS_NXTSTA(x) (x >> DTS_V_2ND) /* Logging */ -#define LOG_MS 0x1 -#define LOG_RW 0x2 -#define LOG_BL 0x4 +#define LOG_MS 0x1 +#define LOG_RW 0x2 +#define LOG_BL 0x4 -#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 */ +#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 FILE *sim_deb; -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_dctime = 40000; /* decel time */ +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_dctime = 40000; /* decel time */ int32 dt_substate = 0; int32 dt_logblk = 0; int32 dt_stopoffr = 0; @@ -308,120 +309,135 @@ 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 + 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 } }; +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) } }; + { 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) +#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 (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) }, - { FLDATA (STOP_OFFR, dt_stopoffr, 0) }, - { ORDATA (DEVADDR, dt_dib.ba, 32), REG_HRO }, - { ORDATA (DEVVEC, dt_dib.vec, 16), REG_HRO }, - { NULL } }; + { 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 (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) }, + { FLDATA (STOP_OFFR, dt_stopoffr, 0) }, + { 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 } }; + { 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 } + }; DEBTAB dt_deb[] = { - { "MOTION", LOG_MS }, - { "DATA", LOG_RW }, - { "BLOCK", LOG_BL }, - { NULL, 0 } }; + { "MOTION", LOG_MS }, + { "DATA", LOG_RW }, + { "BLOCK", LOG_BL }, + { 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_DIS | DEV_UBUS | DEV_DEBUG, 0, - dt_deb, NULL, NULL }; - + "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_DIS | DEV_UBUS | DEV_DEBUG, 0, + dt_deb, NULL, NULL + }; + /* 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 */ +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; } + + 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; } @@ -430,60 +446,71 @@ 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 */ +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; } + + 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) @@ -492,28 +519,29 @@ 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; } +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 + - 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 + - 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 + - schedule acceleration + - set function as next state 4. If not yet at speed, - - set function as next state + - set function as next state 5. If at speed, - - set function as current state, schedule function + - set function as current state, schedule function */ void dt_newsa (int32 newf) @@ -522,51 +550,57 @@ int32 new_unit, prev_mot, new_fnc; int32 prev_dir, new_dir; UNIT *uptr; -new_unit = CSR_GETUNIT (newf); /* new, old units */ +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 ((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 (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_dctime - (dt_dctime >> 2)); /* sched 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_STOP) { /* start? */ + if (dt_setpos (uptr)) return; /* update pos */ + sim_cancel (uptr); /* stop current */ + sim_activate (uptr, dt_dctime - (dt_dctime >> 2)); /* sched 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_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_dctime - (dt_dctime >> 2)); /* sched 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_ACCF) { /* not accel/at speed? */ + if (dt_setpos (uptr)) return; /* update pos */ + sim_cancel (uptr); /* cancel cur */ + sim_activate (uptr, dt_dctime - (dt_dctime >> 2)); /* sched 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; } +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; +return; } - + /* Schedule new DECtape function This routine is only called if @@ -584,95 +618,108 @@ 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 */ +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; +unum = (int32) (uptr - dt_dev.units); if (oldpos == uptr->pos) - uptr->pos = uptr->pos + (dir? -1: 1); + 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 (DEBUG_PRI (dt_dev, LOG_MS)) fprintf (sim_deb, ">>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 (DEBUG_PRI (dt_dev, LOG_RW) || - (DEBUG_PRI (dt_dev, LOG_BL) && (blk == dt_logblk))) - fprintf (sim_deb, ">>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 (DEBUG_PRI (dt_dev, LOG_RW) || - (DEBUG_PRI (dt_dev, LOG_BL) && (blk == dt_logblk))) - fprintf (sim_deb, ">>DT%d: read all block %d %s\n", - unum, blk, (dir? "backward": "forward")); - break; -default: - dt_seterr (uptr, STA_SEL); /* bad state */ - return; } +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 (DEBUG_PRI (dt_dev, LOG_MS)) fprintf (sim_deb, ">>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 (DEBUG_PRI (dt_dev, LOG_RW) || + (DEBUG_PRI (dt_dev, LOG_BL) && (blk == dt_logblk))) + fprintf (sim_deb, ">>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 (DEBUG_PRI (dt_dev, LOG_RW) || + (DEBUG_PRI (dt_dev, LOG_BL) && (blk == dt_logblk))) + fprintf (sim_deb, ">>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) + 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) + 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. @@ -684,40 +731,47 @@ 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_dctime - (dt_dctime >> 2)) / 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 */ +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_dctime - (dt_dctime >> 2)) / 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? */ + detach_unit (uptr); /* off reel? */ uptr->STATE = uptr->pos = 0; - unum = uptr - dt_dev.units; + unum = (int32) (uptr - dt_dev.units); if ((unum == CSR_GETUNIT (tccm)) && (CSR_GETFNC (tccm) != FNC_STOP)) - dt_seterr (uptr, STA_SEL); /* error */ - return TRUE; } + dt_seterr (uptr, STA_SEL); /* error */ + return TRUE; + } return FALSE; } - + /* Command timer service after stop - set done */ t_stat dt_svcdone (UNIT *uptr) @@ -736,7 +790,7 @@ t_stat dt_svc (UNIT *uptr) int32 mot = DTS_GETMOT (uptr->STATE); int32 dir = mot & DTS_DIR; int32 fnc = DTS_GETFNC (uptr->STATE); -int32 *fbuf = uptr->filebuf; +int32 *fbuf = (int32 *) uptr->filebuf; int32 blk, wrd, relpos, dat; uint32 ba, ma; uint16 wbuf; @@ -749,21 +803,26 @@ uint16 wbuf; */ switch (mot) { -case DTS_DECF: case DTS_DECR: /* decelerating */ - if (dt_setpos (uptr)) /* upd pos; off reel? */ - return IORETURN (dt_stopoffr, STOP_DTOFF); - uptr->STATE = DTS_NXTSTA (uptr->STATE); /* advance state */ - if (uptr->STATE) /* not stopped? */ - sim_activate (uptr, dt_dctime - (dt_dctime >> 2)); /* 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; } + + case DTS_DECF: case DTS_DECR: /* decelerating */ + if (dt_setpos (uptr)) /* upd pos; off reel? */ + return IORETURN (dt_stopoffr, STOP_DTOFF); + uptr->STATE = DTS_NXTSTA (uptr->STATE); /* advance state */ + if (uptr->STATE) /* not stopped? */ + sim_activate (uptr, dt_dctime - (dt_dctime >> 2)); /* 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 @@ -771,24 +830,27 @@ default: /* other */ Off reel - detach unit (it must be deselected) */ -if (dt_setpos (uptr)) /* upd pos; off reel? */ - return IORETURN (dt_stopoffr, STOP_DTOFF); -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 # */ +if (dt_setpos (uptr)) /* upd pos; off reel? */ + return IORETURN (dt_stopoffr, STOP_DTOFF); +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; -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 @@ -798,26 +860,29 @@ case DTS_OFR: /* off reel */ 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? */ - ma = (CSR_GETMEX (tccm) << 16) | tcba; /* form 18b addr */ - ba = (blk * DTU_BSIZE (uptr)) + wrd; /* buffer ptr */ - tcdt = wbuf = fbuf[ba] & DMASK; /* read word */ - if (Map_WriteW (ma, 2, &wbuf)) { /* store, nxm? */ - dt_seterr (uptr, STA_NXM); - break; } - 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; + case FNC_READ: /* read */ + wrd = DT_LIN2WD (uptr->pos, uptr); /* get word # */ + if (!dt_substate) { /* !wc ovf? */ + ma = (CSR_GETMEX (tccm) << 16) | tcba; /* form 18b addr */ + ba = (blk * DTU_BSIZE (uptr)) + wrd; /* buffer ptr */ + tcdt = wbuf = fbuf[ba] & DMASK; /* read word */ + if (Map_WriteW (ma, 2, &wbuf)) { /* store, nxm? */ + dt_seterr (uptr, STA_NXM); + break; + } + 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 @@ -829,75 +894,84 @@ case FNC_READ: /* read */ 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_ReadW (ma, 2, &wbuf)) { /* fetch word */ - dt_seterr (uptr, STA_NXM); - break; } - tcdt = wbuf; /* 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 */ - fbuf[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; - + 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_ReadW (ma, 2, &wbuf)) { /* fetch word */ + dt_seterr (uptr, STA_NXM); + break; + } + tcdt = wbuf; /* 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 */ + fbuf[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 = fbuf[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; + 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 = fbuf[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 */ - fbuf[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; } + 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 */ + fbuf[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 */ @@ -906,15 +980,17 @@ void dt_seterr (UNIT *uptr, int32 e) { int32 mot = DTS_GETMOT (uptr->STATE); -tcst = tcst | e; /* set error flag */ +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 */ +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; } @@ -925,12 +1001,13 @@ 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 */ +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; } @@ -940,8 +1017,8 @@ 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 */ +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; } @@ -950,10 +1027,10 @@ return; int32 dt_comobv (int32 dat) { -dat = dat ^ 0777777; /* compl obverse */ +dat = dat ^ 0777777; /* compl obverse */ dat = ((dat >> 15) & 07) | ((dat >> 9) & 070) | - ((dat >> 3) & 0700) | ((dat & 0700) << 3) | - ((dat & 070) << 9) | ((dat & 07) << 15); + ((dat >> 3) & 0700) | ((dat & 0700) << 3) | + ((dat & 070) << 9) | ((dat & 07) << 15); return dat; } @@ -961,14 +1038,15 @@ return dat; int32 dt_csum (UNIT *uptr, int32 blk) { -int32 *fbuf = uptr->filebuf; +int32 *fbuf = (int32 *) 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 = fbuf[ba + i] ^ 0777777; /* get ~word */ - csum = csum ^ (wrd >> 12) ^ (wrd >> 6) ^ wrd; } +csum = 077; /* init csum */ +for (i = 0; i < DTU_BSIZE (uptr); i++) { /* loop thru buf */ + wrd = fbuf[ba + i] ^ 0777777; /* get ~word */ + csum = csum ^ (wrd >> 12) ^ (wrd >> 6) ^ wrd; + } return (csum & 077); } @@ -978,15 +1056,15 @@ 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 077; /* rev csum */ -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 */ +if (wrd == DT_BLKWD) return blk; /* fwd blknum */ +if (wrd == DT_CSMWD) return 077; /* rev csum */ +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) @@ -994,73 +1072,76 @@ 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 */ +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 */ +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)) +#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 */ -}; + 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) { @@ -1074,7 +1155,7 @@ 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 @@ -1092,56 +1173,63 @@ uint32 ba, sz, k, *fbuf; 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 (uptr->fileref)) > 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; } -fbuf = uptr->filebuf; /* file buffer */ +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 (uptr->fileref)) > 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 (uint32)); +if (uptr->filebuf == NULL) { /* can't alloc? */ + detach_unit (uptr); + return SCPE_MEM; + } +fbuf = (uint32 *) 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 */ - fbuf[ba] = ((uint32) (pdp8b[k] & 07777) << 6) | - ((uint32) (pdp8b[k + 1] >> 6) & 077); - fbuf[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++) - fbuf[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 */ +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 */ + fbuf[ba] = ((uint32) (pdp8b[k] & 07777) << 6) | + ((uint32) (pdp8b[k + 1] >> 6) & 077); + fbuf[ba + 1] = ((uint32) (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 (uint16), D18_BSIZE, uptr->fileref); + if (k == 0) break; + for ( ; k < D18_BSIZE; k++) pdp11b[k] = 0; + for (k = 0; k < D18_BSIZE; k++) + fbuf[ba++] = pdp11b[k]; + } + uptr->hwmark = ba; + } /* end elif */ +else uptr->hwmark = fxread (uptr->filebuf, sizeof (uint32), + 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; } @@ -1162,42 +1250,48 @@ uint32 ba, k, *fbuf; 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; } -fbuf = 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] = (fbuf[ba] >> 6) & 07777; - pdp8b[k + 1] = ((fbuf[ba] & 077) << 6) | - ((fbuf[ba + 1] >> 12) & 077); - pdp8b[k + 2] = fbuf[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] = fbuf[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 */ +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; + } +fbuf = (uint32 *) 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] = (fbuf[ba] >> 6) & 07777; + pdp8b[k + 1] = ((fbuf[ba] & 077) << 6) | + ((fbuf[ba + 1] >> 12) & 077); + pdp8b[k + 2] = fbuf[ba + 1] & 07777; + ba = ba + 2; + } /* end loop blk */ + fxwrite (pdp8b, sizeof (uint16), 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] = fbuf[ba++] & DMASK; + fxwrite (pdp11b, sizeof (uint16), D18_BSIZE, uptr->fileref); + if (ferror (uptr->fileref)) break; + } /* end loop file */ + } /* end if 16b */ + else fxwrite (uptr->filebuf, sizeof (uint32), /* 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 index f7c24abe..aee5802d 100644 --- a/PDP11/pdp11_tm.c +++ b/PDP11/pdp11_tm.c @@ -19,60 +19,62 @@ 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 + 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 + tm TM11/TU10 magtape - 18-Mar-05 RMS Added attached test to detach routine - 07-Dec-04 RMS Added read-only file support - 30-Sep-04 RMS Revised Unibus interface - 25-Jan-04 RMS Revised for device debug support - 29-Dec-03 RMS Added 18b Qbus support - 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 + 16-Aug-05 RMS Fixed C++ declaration and cast problems + 07-Jul-05 RMS Removed extraneous externs + 18-Mar-05 RMS Added attached test to detach routine + 07-Dec-04 RMS Added read-only file support + 30-Sep-04 RMS Revised Unibus interface + 25-Jan-04 RMS Revised for device debug support + 29-Dec-03 RMS Added 18b Qbus support + 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 + 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. @@ -82,87 +84,86 @@ #include "pdp11_defs.h" #include "sim_tape.h" -#define TM_NUMDR 8 /* #drives */ -#define USTAT u3 /* unit status */ +#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) +#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_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 */ +#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 */ +#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 FILE *sim_deb; -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 */ +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); @@ -180,177 +181,203 @@ 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 + 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 } }; +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_ROABLE +UNIT_DISABLE, 0) }, - { UDATA (&tm_svc, UNIT_ATTABLE + UNIT_ROABLE +UNIT_DISABLE, 0) }, - { UDATA (&tm_svc, UNIT_ATTABLE + UNIT_ROABLE +UNIT_DISABLE, 0) }, - { UDATA (&tm_svc, UNIT_ATTABLE + UNIT_ROABLE +UNIT_DISABLE, 0) }, - { UDATA (&tm_svc, UNIT_ATTABLE + UNIT_ROABLE +UNIT_DISABLE, 0) }, - { UDATA (&tm_svc, UNIT_ATTABLE + UNIT_ROABLE +UNIT_DISABLE, 0) }, - { UDATA (&tm_svc, UNIT_ATTABLE + UNIT_ROABLE +UNIT_DISABLE, 0) }, - { UDATA (&tm_svc, UNIT_ATTABLE + UNIT_ROABLE +UNIT_DISABLE, 0) } }; + { UDATA (&tm_svc, UNIT_ATTABLE + UNIT_ROABLE +UNIT_DISABLE, 0) }, + { UDATA (&tm_svc, UNIT_ATTABLE + UNIT_ROABLE +UNIT_DISABLE, 0) }, + { UDATA (&tm_svc, UNIT_ATTABLE + UNIT_ROABLE +UNIT_DISABLE, 0) }, + { UDATA (&tm_svc, UNIT_ATTABLE + UNIT_ROABLE +UNIT_DISABLE, 0) }, + { UDATA (&tm_svc, UNIT_ATTABLE + UNIT_ROABLE +UNIT_DISABLE, 0) }, + { UDATA (&tm_svc, UNIT_ATTABLE + UNIT_ROABLE +UNIT_DISABLE, 0) }, + { UDATA (&tm_svc, UNIT_ATTABLE + UNIT_ROABLE +UNIT_DISABLE, 0) }, + { UDATA (&tm_svc, UNIT_ATTABLE + UNIT_ROABLE +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 } }; + { 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 } }; + { 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 | DEV_Q18 | DEV_DEBUG }; - -/* I/O dispatch routine, I/O addresses 17772520 - 17772532 + "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 | DEV_Q18 | DEV_DEBUG + }; - 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 +/* I/O dispatch routines, 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; } +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 */ +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 = 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 */ + 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 */ +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 @@ -364,100 +391,104 @@ 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 */ +u = (int32) (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->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 ((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 (DEBUG_PRS (tm_dev)) fprintf (sim_deb, - ">>TM: op=%o, ma=%o, bc=%o, pos=%d\n", f, xma, cbc, uptr->pos); -switch (f) { /* case on function */ - -/* Unit service, continued */ + ">>TM: op=%o, ma=%o, bc=%o, pos=%d\n", f, xma, cbc, uptr->pos); +switch (f) { /* case on function */ -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)) { /* 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_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)) { /* 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)) { /* 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_WRITE: /* write */ + case MTC_WREXT: /* write ext gap */ + if (t = Map_ReadB (xma, cbc, tmxb)) { /* 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; -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_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_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 */ + 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 */ +tm_ca = xma & 0177777; /* update mem addr */ +tm_set_done (); /* set done */ +tm_updcsta (uptr); /* update status */ if (DEBUG_PRS (tm_dev)) fprintf (sim_deb, - ">>TM: sta=%o, ma=%o, wc=%o, pos=%d\n", - tm_sta, tm_ca, tm_bc, uptr->pos); + ">>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) @@ -485,36 +516,46 @@ return; 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; } + + 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) @@ -522,18 +563,19 @@ t_stat tm_reset (DEVICE *dptr) int32 u; UNIT *uptr; -tm_cmd = MTC_DONE; /* set done */ +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 (uint8)); +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 = (uint8 *) calloc (MT_MAXFR, sizeof (uint8)); if (tmxb == NULL) return SCPE_MEM; return SCPE_OK; } @@ -563,7 +605,7 @@ 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) @@ -589,58 +631,58 @@ return SCPE_OK; 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)) +#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 */ -}; + 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 */ -}; + 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) { @@ -650,10 +692,13 @@ 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]; } + 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; diff --git a/PDP11/pdp11_tq.c b/PDP11/pdp11_tq.c index 316f70e0..a2970790 100644 --- a/PDP11/pdp11_tq.c +++ b/PDP11/pdp11_tq.c @@ -1,6 +1,6 @@ /* pdp11_tq.c: TMSCP tape controller simulator - Copyright (c) 2002-2004, Robert M Supnik + Copyright (c) 2002-2005, 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"), @@ -19,42 +19,44 @@ 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 + 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 + tq TQK50 tape controller - 30-Sep-04 RMS Revised Unibus interface - 12-Jun-04 RMS Fixed bug in reporting write protect (reported by Lyle Bickley) - 18-Apr-04 RMS Fixed TQK70 media ID and model byte (found by Robert Schaffrath) - 26-Mar-04 RMS Fixed warnings with -std=c99 - 25-Jan-04 RMS Revised for device debug support - 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) + 16-Aug-05 RMS Fixed C++ declaration and cast problems + 22-Jul-05 RMS Fixed warning from Solaris C (from Doug Gwyn) + 30-Sep-04 RMS Revised Unibus interface + 12-Jun-04 RMS Fixed bug in reporting write protect (reported by Lyle Bickley) + 18-Apr-04 RMS Fixed TQK70 media ID and model byte (found by Robert Schaffrath) + 26-Mar-04 RMS Fixed warnings with -std=c99 + 25-Jan-04 RMS Revised for device debug support + 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 */ +#if defined (VM_PDP10) /* PDP10 version */ #error "TQK50 not supported on PDP-10!" -#elif defined (VM_VAX) /* VAX version */ +#elif defined (VM_VAX) /* VAX version */ #include "vax_defs.h" #if (UNIBUS) -#define INIT_TYPE TQ8_TYPE +#define INIT_TYPE TQ8_TYPE #else -#define INIT_TYPE TQ5_TYPE +#define INIT_TYPE TQ5_TYPE #endif -#else /* PDP-11 version */ +#else /* PDP-11 version */ #include "pdp11_defs.h" -#define INIT_TYPE TQ5_TYPE +#define INIT_TYPE TQ5_TYPE extern int32 cpu_opt; #endif @@ -62,153 +64,155 @@ extern int32 cpu_opt; #include "pdp11_mscp.h" #include "sim_tape.h" -#define UF_MSK (UF_SCH|UF_VSS|UF_CMR|UF_CMW) /* settable flags */ +#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_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_SH_ALL 017 /* show all */ -#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 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))? UF_WPH: 0) +#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))? 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 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 tq_comm tq_rq.ba -#define ERR 0 /* must be SCPE_OK! */ -#define OK 1 +#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 */ -#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)) +#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 */ + 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 +#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 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 14 /* unit ID */ -#define TQ7_MED 0x6D68B046 /* 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 TQ7_TYPE 1 /* TK70 */ +#define TQ7_UQPM 14 /* UQ port ID */ +#define TQ7_CMOD 14 /* ctrl ID */ +#define TQ7_UMOD 14 /* unit ID */ +#define TQ7_MED 0x6D68B046 /* 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 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 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 + 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)) +#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; -}; + 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" }, -}; - + { TQ_DRV (TQ5), "TK50" }, + { TQ_DRV (TQ7), "TK70" }, + { TQ_DRV (TQ8), "TU81" }, + { TQ_DRV (TQU), "TKUSER" }, + }; + /* Data */ extern int32 int_req[IPL_HLVL]; @@ -217,67 +221,68 @@ extern UNIT cpu_unit; extern FILE *sim_deb; 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 = INIT_TYPE; /* device type */ +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 = INIT_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 }; - + 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; @@ -343,149 +348,163 @@ 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 + 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 } }; +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) } }; + { 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) +#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 } }; + { 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 }, + { 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, TQ_SH_ALL, "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 }, + { MTAB_XTD|MTAB_VDV, 004, "ADDRESS", "ADDRESS", + &set_addr, &show_addr, NULL }, #else - { MTAB_XTD|MTAB_VDV, 004, "ADDRESS", NULL, - NULL, &show_addr, NULL }, + { MTAB_XTD|MTAB_VDV, 004, "ADDRESS", NULL, + NULL, &show_addr, NULL }, #endif - { MTAB_XTD|MTAB_VDV, 0, "VECTOR", NULL, - NULL, &show_vec, NULL }, - { 0 } }; + { 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 | DEV_DEBUG }; - -/* I/O dispatch routine, I/O addresses 17772150 - 17772152 + "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 | DEV_DEBUG + }; - 17772150 IP read/write - 17772152 SA read/write +/* I/O dispatch routines, 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; } +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 (DEBUG_PRS (tq_dev)) fprintf (sim_deb, - ">>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; } +switch ((PA >> 1) & 01) { /* decode PA<1> */ + + case 0: /* IP */ + tq_reset (&tq_dev); /* init device */ + if (DEBUG_PRS (tq_dev)) fprintf (sim_deb, + ">>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; } @@ -497,27 +516,27 @@ 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 */ +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)) /* zero comm area */ - return tq_fatal (PE_QWE); /* error? */ +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)) /* 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 */ + ((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. @@ -535,91 +554,107 @@ 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 (DEBUG_PRS (tq_dev)) fprintf (sim_deb, - ">>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 */ +if (tq_csta < CST_UP) { /* still init? */ + switch (tq_csta) { /* controller state? */ -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? */ + 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 (DEBUG_PRS (tq_dev)) fprintf (sim_deb, + ">>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 (DEBUG_PRS (tq_dev)) { UNIT *up = tq_getucb (tq_pkt[pkt].d[CMD_UN]); - fprintf (sim_deb, ">>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_deb, "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_deb, ", pos=%d, obj=%d\n", up->pos, up->objp); - else fprintf (sim_deb, "\n"); - fflush (sim_deb); } - 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 */ + fprintf (sim_deb, ">>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_deb, "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_deb, ", pos=%d, obj=%d\n", up->pos, up->objp); + else fprintf (sim_deb, "\n"); + fflush (sim_deb); + } + 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) */ @@ -629,88 +664,109 @@ 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 */ +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 # */ +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; } +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_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; + 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 */ + 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); } @@ -719,33 +775,39 @@ return tq_putpkt (pkt, TRUE); t_bool tq_abo (int32 pkt) { -uint32 lu = tq_pkt[pkt].d[CMD_UN]; /* unit # */ -uint32 ref = GETP32 (pkt, ABO_REFL); /* cmd ref # */ +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 */ +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); } @@ -755,22 +817,25 @@ return tq_putpkt (pkt, TRUE); 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 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 */ +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); } @@ -779,17 +844,18 @@ return tq_putpkt (pkt, TRUE); t_bool tq_gcs (int32 pkt) { -uint32 lu = tq_pkt[pkt].d[CMD_UN]; /* unit # */ -uint32 ref = GETP32 (pkt, GCS_REFL); /* ref # */ +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]; } +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); @@ -799,26 +865,28 @@ return tq_putpkt (pkt, TRUE); t_bool tq_gus (int32 pkt) { -uint32 lu = tq_pkt[pkt].d[CMD_UN]; /* unit # */ +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 */ +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); } @@ -827,23 +895,26 @@ return tq_putpkt (pkt, TRUE); t_bool tq_onl (int32 pkt) { -uint32 lu = tq_pkt[pkt].d[CMD_UN]; /* unit # */ +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 */ +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); } @@ -852,56 +923,60 @@ return tq_putpkt (pkt, TRUE); 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); - } +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 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 */ +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 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 */ +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); } @@ -910,18 +985,20 @@ return tq_putpkt (pkt, TRUE); t_bool tq_erase (int32 pkt) { -uint32 lu = tq_pkt[pkt].d[CMD_UN]; /* unit # */ -uint32 cmd = GETP (pkt, CMD_OPC, OPC); /* opcode */ +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 */ +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); } @@ -930,19 +1007,21 @@ return tq_putpkt (pkt, TRUE); t_bool tq_wtm (int32 pkt) { -uint32 lu = tq_pkt[pkt].d[CMD_UN]; /* unit # */ +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 */ +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); } @@ -951,50 +1030,56 @@ return tq_putpkt (pkt, TRUE); t_bool tq_pos (int32 pkt) { -uint32 lu = tq_pkt[pkt].d[CMD_UN]; /* unit # */ +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 */ +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 */ +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 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 */ +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); } @@ -1003,19 +1088,22 @@ return tq_putpkt (pkt, TRUE); 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! */ +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 */ @@ -1024,138 +1112,155 @@ 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 */ +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 (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 */ +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)) { /* 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)) { /* 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_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)) { /* 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)) { /* 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)) { /* 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_WR: /* write */ + if (t = Map_ReadB (ba, bc, tqxb)) { /* 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_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_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; + 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 */ + default: + return SCPE_IERR; + } + +tq_mot_end (uptr, 0, sts, tbc); /* done */ return SCPE_OK; } @@ -1163,9 +1268,9 @@ return SCPE_OK; 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 */ +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; @@ -1175,59 +1280,70 @@ return SCPE_IOERR; 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 */ +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 */ +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 */ +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 */ +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; } +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; } @@ -1237,22 +1353,25 @@ 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 */ +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; } @@ -1261,10 +1380,11 @@ 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; } +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; } @@ -1274,13 +1394,14 @@ 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 */ +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; } @@ -1289,27 +1410,29 @@ 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? */ +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 */ +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; } @@ -1317,16 +1440,17 @@ 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 */ +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) @@ -1334,30 +1458,30 @@ 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 # */ +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[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 */ + (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 */ + (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); } @@ -1368,21 +1492,21 @@ 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 */ +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 */ + (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 */ +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); } @@ -1393,14 +1517,14 @@ 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 */ +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); + (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); @@ -1415,60 +1539,62 @@ 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 */ +if (!tq_deqf (&pkt)) return ERR; /* get log pkt */ +lu = (uint32) (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 */ +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 + 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 */ +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 */ +int32 ptr = *lh; /* head of list */ -if (ptr) *lh = tq_pkt[ptr].link; /* next */ +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 */ +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 */ +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 */ @@ -1477,16 +1603,17 @@ 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 (!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)) - return tq_fatal (PE_PRE); /* read pkt */ -return tq_putdesc (&tq_cq, desc); /* release desc */ + 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. @@ -1498,33 +1625,36 @@ t_bool tq_putpkt (int32 pkt, t_bool qt) { uint32 addr, desc, lnt, cr; -if (pkt == 0) return OK; /* any packet? */ +if (pkt == 0) return OK; /* any packet? */ if (DEBUG_PRS (tq_dev)) { - UNIT *up = tq_getucb (tq_pkt[pkt].d[CMD_UN]); - fprintf (sim_deb, ">>TQ: rsp=%04X, sts=%04X", - tq_pkt[pkt].d[RSP_OPF], tq_pkt[pkt].d[RSP_STS]); - if (up) fprintf (sim_deb, ", pos=%d, obj=%d\n", up->pos, up->objp); - else fprintf (sim_deb, "\n"); - fflush (sim_deb); } -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); } + UNIT *up = tq_getucb (tq_pkt[pkt].d[CMD_UN]); + fprintf (sim_deb, ">>TQ: rsp=%04X, sts=%04X", + tq_pkt[pkt].d[RSP_OPF], tq_pkt[pkt].d[RSP_STS]); + if (up) fprintf (sim_deb, ", pos=%d, obj=%d\n", up->pos, up->objp); + else fprintf (sim_deb, "\n"); + fflush (sim_deb); + } +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)) - 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 */ + 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 */ @@ -1534,8 +1664,8 @@ 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)) /* fetch desc */ - return tq_fatal (PE_QRE); /* err? dead */ +if (Map_ReadW (addr, 4, d)) /* fetch desc */ + return tq_fatal (PE_QRE); /* err? dead */ *desc = ((uint32) d[0]) | (((uint32) d[1]) << 16); return OK; } @@ -1552,22 +1682,25 @@ 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[0] = newd & 0xFFFF; /* 32b to 16b */ d[1] = (newd >> 16) & 0xFFFF; -if (Map_WriteW (addr, 4, d)) /* 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)) /* read prv */ - return tq_fatal (PE_QRE); - prvd = ((uint32) d[0]) | (((uint32) d[1]) << 16); - if (prvd & UQ_DESC_OWN) tq_ring_int (ring); } } +if (Map_WriteW (addr, 4, d)) /* 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)) /* 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 */ @@ -1585,10 +1718,10 @@ return uptr; 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... */ +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; } @@ -1598,10 +1731,11 @@ 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 */ +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; } @@ -1609,21 +1743,22 @@ return t; 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_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 */ + (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; } @@ -1631,12 +1766,12 @@ return; 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_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 */ +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; } @@ -1652,11 +1787,11 @@ return; void tq_ring_int (struct uq_ring *ring) { -uint32 iadr = tq_comm + ring->ioff; /* addr intr wd */ +uint32 iadr = tq_comm + ring->ioff; /* addr intr wd */ uint16 flag = 1; -Map_WriteW (iadr, 2, &flag); /* write flag */ -if (tq_dib.vec) SET_INT (TQ); /* if enb, intr */ +Map_WriteW (iadr, 2, &flag); /* write flag */ +if (tq_dib.vec) SET_INT (TQ); /* if enb, intr */ return; } @@ -1664,7 +1799,7 @@ return; int32 tq_inta (void) { -return tq_dib.vec; /* prog vector */ +return tq_dib.vec; /* prog vector */ } /* Fatal error */ @@ -1672,13 +1807,13 @@ return tq_dib.vec; /* prog vector */ t_bool tq_fatal (uint32 err) { if (DEBUG_PRS (tq_dev)) fprintf (sim_deb, ">>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 */ +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) @@ -1688,7 +1823,7 @@ 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); + ~(UNIT_SXC | UNIT_POL | UNIT_TMK); return SCPE_OK; } @@ -1698,10 +1833,10 @@ t_stat tq_detach (UNIT *uptr) { t_stat r; -r = sim_tape_detach (uptr); /* detach unit */ +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 */ +uptr->uf = 0; /* clr unit flgs */ return SCPE_OK; } @@ -1712,147 +1847,149 @@ 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 */ -if (UNIBUS) tq_sa = SA_S1 | SA_S1C_DI | SA_S1C_MP; /* Unibus? */ +tq_csta = CST_S1; /* init stage 1 */ +tq_s1dat = 0; /* no S1 data */ +tq_dib.vec = 0; /* no vector */ +if (UNIBUS) tq_sa = SA_S1 | SA_S1C_DI | SA_S1C_MP; /* Unibus? */ else 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)); +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 = (uint8 *) 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)) +#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 # */ +#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" */ + 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 */ + 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 */ + /* 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? */ + 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 */ + /* 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 */ + 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 */ + /* 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 */ + 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 */ -}; + 0100000, /* cmdtbl: init step 1 */ + B_RING, /* ring base */ + 0000000, /* high ring base */ + 0000001 /* go */ + }; t_stat tq_boot (int32 unitno, DEVICE *dptr) { @@ -1875,7 +2012,7 @@ return SCPE_NOFNC; } #endif - + /* Special show commands */ void tq_show_ring (FILE *st, struct uq_ring *rp) @@ -1885,22 +2022,23 @@ 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); + 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); + 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)) { - fprintf (st, " %3d: non-existent memory\n", i); - break; } - desc = ((uint32) d[0]) | (((uint32) d[1]) << 16); + if (Map_ReadW (rp->ba + (i << 2), 4, d)) { + 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); + fprintf (st, " %3d: %011o\n", i, desc); #else - fprintf (st, " %3d: %08x\n", i, desc); + fprintf (st, " %3d: %08x\n", i, desc); #endif - } + } return; } @@ -1912,17 +2050,17 @@ 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); + 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++) + 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]); + fprintf (st, " %06o", tq_pkt[pkt].d[j]); #else - fprintf (st, " %04x", tq_pkt[pkt].d[j]); + fprintf (st, " %04x", tq_pkt[pkt].d[j]); #endif - fprintf (st, "\n"); - } + fprintf (st, "\n"); + } return; } @@ -1931,20 +2069,25 @@ 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; } + 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->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); } } + 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; } @@ -1955,7 +2098,8 @@ int32 i, pkt; if (tq_csta != CST_UP) { fprintf (st, "Controller is not initialized\n"); - return SCPE_OK; } + 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); @@ -1966,23 +2110,27 @@ if (val & TQ_SH_RI) { } 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"); } + 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); } + 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); + tq_show_unitq (st, &tq_unit[i], 0, NULL); } return SCPE_OK; } @@ -1996,13 +2144,15 @@ 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; + return SCPE_ARG; for (i = 0; i < TQ_NUMDR; i++) { - if (tq_unit[i].flags & UNIT_ATT) return SCPE_ALATT; } + 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; } + 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; } diff --git a/PDP11/pdp11_ts.c b/PDP11/pdp11_ts.c index 2ee363ca..a17ed4c6 100644 --- a/PDP11/pdp11_ts.c +++ b/PDP11/pdp11_ts.c @@ -19,52 +19,54 @@ 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 + 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 + ts TS11/TSV05 magtape - 18-Mar-05 RMS Added attached test to detach routine - 07-Dec-04 RMS Added read-only file support - 30-Sep-04 RMS Revised Unibus interface - 25-Jan-04 RMS Revised for device debug support - 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) + 16-Aug-05 RMS Fixed C++ declaration and cast problems + 07-Jul-05 RMS Removed extraneous externs + 18-Mar-05 RMS Added attached test to detach routine + 07-Dec-04 RMS Added read-only file support + 30-Sep-04 RMS Revised Unibus interface + 25-Jan-04 RMS Revised for device debug support + 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 + 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. @@ -79,204 +81,203 @@ - VAX Q22 systems - the TS11 must go through the I/O map */ -#if defined (VM_PDP10) /* PDP10 version */ +#if defined (VM_PDP10) /* PDP10 version */ #error "TS11 not supported on PDP10!" -#elif defined (VM_VAX) /* VAX version */ +#elif defined (VM_VAX) /* VAX version */ #include "vax_defs.h" -#define TS_DIS 0 /* on by default */ -#define DMASK 0xFFFF +#define TS_DIS 0 /* on by default */ +#define DMASK 0xFFFF -#else /* PDP-11 version */ +#else /* PDP-11 version */ #include "pdp11_defs.h" -#define TS_DIS DEV_DIS /* off by default */ +#define TS_DIS DEV_DIS /* off by default */ extern int32 cpu_opt; #endif #include "sim_tape.h" -#define ADDRTEST (UNIBUS? 0177774: 0177700) - +#define ADDRTEST (UNIBUS? 0177774: 0177700) + /* TSBA/TSDB - 17772520: base address/data buffer register - read: most recent memory address - write word: initiate command - write byte: diagnostic use + 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 + 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 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 */ +#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 */ +#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) +#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 */ +#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 */ +#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 */ +#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 */ +#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 */ +#define XS1_UCOR 0000002 /* uncorrectable */ /* Extended status register 2 */ -#define XS2_XTF 0000200 /* ext features */ +#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 */ +#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 */ +#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 */ +#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 */ +#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 WCHX_HDS 0000040 /* high density */ + +#define MAX(a,b) (((a) >= (b))? (a): (b)) +#define MAX_PLNT 8 /* max pkt length */ -#define MAX(a,b) (((a) >= (b))? (a): (b)) -#define MAX_PLNT 8 /* max pkt length */ - extern int32 int_req[IPL_HLVL]; -extern int32 int_vec[IPL_HLVL][32]; extern UNIT cpu_unit; extern FILE *sim_deb; -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 */ -static uint16 cpy_buf[MAX_PLNT]; /* copy buffer */ +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 */ +static uint16 cpy_buf[MAX_PLNT]; /* copy buffer */ DEVICE ts_dev; t_stat ts_rd (int32 *data, int32 PA, int32 access); @@ -294,81 +295,89 @@ 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 + 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 } }; +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_ROABLE + 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 } }; + { 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 } }; + { 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 | DEV_DEBUG }; - -/* I/O dispatch routine, I/O addresses 17772520 - 17772522 + "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 | DEV_DEBUG + }; - 17772520 TSBA read/write - 17772522 TSSR read/write +/* I/O dispatch routines, 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; } +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; } @@ -376,73 +385,90 @@ t_stat ts_wr (int32 data, int32 PA, int32 access) { int32 i, t; -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 */ - t = Map_ReadW (tsba, CMD_PLNT << 1, cpy_buf); /* read cmd pkt */ - tsba = tsba + ((CMD_PLNT << 1) - t); /* incr tsba */ - if (t) { /* nxm? */ - ts_endcmd (TSSR_NXM + TC5, 0, MSG_ACK|MSG_MNEF|MSG_CFAIL); - return SCPE_OK; } - for (i = 0; i < CMD_PLNT; i++) /* copy packet */ - tscmdp[i] = cpy_buf[i]; - 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; } +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 */ + t = Map_ReadW (tsba, CMD_PLNT << 1, cpy_buf); /* read cmd pkt */ + tsba = tsba + ((CMD_PLNT << 1) - t); /* incr tsba */ + if (t) { /* nxm? */ + ts_endcmd (TSSR_NXM + TC5, 0, MSG_ACK|MSG_MNEF|MSG_CFAIL); + return SCPE_OK; + } + for (i = 0; i < CMD_PLNT; i++) /* copy packet */ + tscmdp[i] = cpy_buf[i]; + 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) +#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)); } + + 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; } @@ -451,13 +477,13 @@ 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); +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; } @@ -469,19 +495,20 @@ 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); +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; } @@ -490,13 +517,13 @@ 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); +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; } @@ -507,22 +534,23 @@ 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); +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; @@ -530,30 +558,34 @@ t_mtrlnt i, t, tbc, wbc; int32 wa; 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 */ -if (cmdhdr & CMD_SWP) { /* swapped? */ - for (i = 0; i < wbc; i++) { /* copy buffer */ - wa = tsba ^ 1; /* apply OPP */ - if (Map_WriteB (tsba, 1, &tsxb[i])) { /* store byte, nxm? */ - tssr = ts_updtssr (tssr | TSSR_NXM); /* set error */ - return (XTC (XS0_RLS, TC4)); } - tsba = tsba + 1; - msgrfc = (msgrfc - 1) & DMASK; } - } -else { t = Map_WriteB (tsba, wbc, tsxb); /* store record */ - tsba = tsba + (wbc - t); /* update tsba */ - if (t) { /* nxm? */ - tssr = ts_updtssr (tssr | TSSR_NXM); /* set error */ - return (XTC (XS0_RLS, TC4)); } - msgrfc = (msgrfc - (wbc - t)) & DMASK; /* update fc */ - } -if (msgrfc) return (XTC (XS0_RLS, TC2)); /* buf too big? */ -if (tbc > wbc) return (XTC (XS0_RLL, TC2)); /* rec too big? */ +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 */ +if (cmdhdr & CMD_SWP) { /* swapped? */ + for (i = 0; i < wbc; i++) { /* copy buffer */ + wa = tsba ^ 1; /* apply OPP */ + if (Map_WriteB (tsba, 1, &tsxb[i])) { /* store byte, nxm? */ + tssr = ts_updtssr (tssr | TSSR_NXM); /* set error */ + return (XTC (XS0_RLS, TC4)); + } + tsba = tsba + 1; + msgrfc = (msgrfc - 1) & DMASK; + } + } +else { + t = Map_WriteB (tsba, wbc, tsxb); /* store record */ + tsba = tsba + (wbc - t); /* update tsba */ + if (t) { /* nxm? */ + tssr = ts_updtssr (tssr | TSSR_NXM); /* set error */ + return (XTC (XS0_RLS, TC4)); + } + msgrfc = (msgrfc - (wbc - t)) & DMASK; /* update fc */ + } +if (msgrfc) return (XTC (XS0_RLS, TC2)); /* buf too big? */ +if (tbc > wbc) return (XTC (XS0_RLL, TC2)); /* rec too big? */ return 0; } @@ -564,24 +596,26 @@ t_mtrlnt i, tbc, wbc; int32 wa; 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_WriteB (wa, 1, &tsxb[i - 1])) { /* store byte, nxm? */ - 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? */ +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_WriteB (wa, 1, &tsxb[i - 1])) { /* store byte, nxm? */ + 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, t; @@ -589,25 +623,29 @@ uint32 wa; t_stat st; msgrfc = fc; -if (fc == 0) fc = 0200000; /* byte count */ -tsba = (cmdadh << 16) | cmdadl; /* buf addr */ -if (cmdhdr & CMD_SWP) { /* swapped? */ - for (i = 0; i < fc; i++) { /* copy mem to buf */ - wa = tsba ^ 1; /* apply OPP */ - if (Map_ReadB (wa, 1, &tsxb[i])) { /* fetch byte, nxm? */ - tssr = ts_updtssr (tssr | TSSR_NXM); - return TC5; } - tsba = tsba + 1; } - } -else { t = Map_ReadB (tsba, fc, tsxb); /* fetch record */ - tsba = tsba + (fc - t); /* update tsba */ - if (t) { /* nxm? */ - tssr = ts_updtssr (tssr | TSSR_NXM); - return TC5; } - } -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 */ +if (fc == 0) fc = 0200000; /* byte count */ +tsba = (cmdadh << 16) | cmdadl; /* buf addr */ +if (cmdhdr & CMD_SWP) { /* swapped? */ + for (i = 0; i < fc; i++) { /* copy mem to buf */ + wa = tsba ^ 1; /* apply OPP */ + if (Map_ReadB (wa, 1, &tsxb[i])) { /* fetch byte, nxm? */ + tssr = ts_updtssr (tssr | TSSR_NXM); + return TC5; + } + tsba = tsba + 1; + } + } +else { + t = Map_ReadB (tsba, fc, tsxb); /* fetch record */ + tsba = tsba + (fc - t); /* update tsba */ + if (t) { /* nxm? */ + tssr = ts_updtssr (tssr | TSSR_NXM); + return TC5; + } + } +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; } @@ -616,213 +654,265 @@ 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 */ +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, t, bc, fnc, mod, st0, st1; -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_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 */ + 0, 0, 0, 0, 0, 0, 0, 0, /* 20 - 27 */ + 0, 0, 0, 0, 0, 0, 0, 0 /* 30 - 37 */ + }; static const char *fnc_name[CMD_N_FNC] = { "0", "READ", "2", "3", "WCHR", "WRITE", "WSSM", "7", "POS", "FMT", "CTL", "INIT", "14", "15", "16", "GSTA", "20", "21", "22", "23", "24", "25", "26", "27", - "30", "31", "32", "33", "34", "35", "36", "37" }; + "30", "31", "32", "33", "34", "35", "36", "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 (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 */ +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 (DEBUG_PRS (ts_dev)) - fprintf (sim_deb, ">>TS: cmd=%s, mod=%o, buf=%o, lnt=%d, pos=%d\n", - fnc_name[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; } - + fprintf (sim_deb, ">>TS: cmd=%s, mod=%o, buf=%o, lnt=%d, pos=%d\n", + fnc_name[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; - bc = ((WCH_PLNT << 1) > cmdlnt)? cmdlnt: WCH_PLNT << 1; - t = Map_ReadW (tsba, bc, cpy_buf); /* fetch packet */ - tsba = tsba + (bc - t); /* inc tsba */ - if (t) { /* nxm? */ - ts_endcmd (TSSR_NBA | TSSR_NXM | TC5, 0, 0); - return SCPE_OK; } - for (i = 0; i < (bc / 2); i++) /* copy packet */ - tswchp[i] = cpy_buf[i]; - 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; } +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; + bc = ((WCH_PLNT << 1) > cmdlnt)? cmdlnt: WCH_PLNT << 1; + t = Map_ReadW (tsba, bc, cpy_buf); /* fetch packet */ + tsba = tsba + (bc - t); /* inc tsba */ + if (t) { /* nxm? */ + ts_endcmd (TSSR_NBA | TSSR_NXM | TC5, 0, 0); + return SCPE_OK; + } + for (i = 0; i < (bc / 2); i++) /* copy packet */ + tswchp[i] = cpy_buf[i]; + 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: /* position */ + 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) @@ -837,9 +927,10 @@ 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; } + 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; @@ -852,14 +943,15 @@ 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 }; + 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 */ +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 */ +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; } @@ -867,29 +959,30 @@ void ts_endcmd (int32 tc, int32 xs0, int32 msg) { int32 i, t; -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++) - cpy_buf[i] = (uint16) tsmsgp[i]; /* copy buffer */ - t = Map_WriteW (tsba, i << 1, cpy_buf); /* write to mem */ - tsba = tsba + ((i << 1) - t); /* incr tsba */ - if (t) { /* nxm? */ - tssr = tssr | TSSR_NXM; - tc = (tc & ~TSSR_TC) | TC4; } - } +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++) + cpy_buf[i] = (uint16) tsmsgp[i]; /* copy buffer */ + t = Map_WriteW (tsba, i << 1, cpy_buf); /* write to mem */ + tsba = tsba + ((i << 1) - t); /* incr tsba */ + if (t) { /* nxm? */ + tssr = tssr | TSSR_NXM; + tc = (tc & ~TSSR_TC) | TC4; + } + } 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 (DEBUG_PRS (ts_dev)) - fprintf (sim_deb, ">>TS: sta=%o, tc=%o, rfc=%d, pos=%d\n", - msgxs0, GET_TC (tssr), msgrfc, ts_unit.pos); + fprintf (sim_deb, ">>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) @@ -907,7 +1000,7 @@ 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 (uint8)); +if (tsxb == NULL) tsxb = (uint8 *) calloc (MT_MAXFR, sizeof (uint8)); if (tsxb == NULL) return SCPE_MEM; return SCPE_OK; } @@ -918,15 +1011,16 @@ 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 */ +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; } @@ -936,64 +1030,65 @@ t_stat ts_detach (UNIT* uptr) { t_stat r; -if (!(uptr->flags & UNIT_ATT)) return SCPE_OK; /* attached? */ -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 */ +if (!(uptr->flags & UNIT_ATT)) return SCPE_OK; /* attached? */ +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)) +#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 */ -}; + 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) { @@ -1003,7 +1098,7 @@ extern uint16 *M; sim_tape_rewind (&ts_unit); for (i = 0; i < BOOT_LEN; i++) - M[(BOOT_START >> 1) + i] = boot_rom[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; diff --git a/PDP11/pdp11_tu.c b/PDP11/pdp11_tu.c index 56aee0bf..72ba8ced 100644 --- a/PDP11/pdp11_tu.c +++ b/PDP11/pdp11_tu.c @@ -19,26 +19,27 @@ 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 + 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 TM02/TM03 magtape + tu TM02/TM03 magtape - 31-Mar-05 RMS Fixed inaccuracies in error reporting - 18-Mar-05 RMS Added attached test to detach routine - 10-Sep-04 RMS Cloned from pdp10_tu.c + 16-Aug-05 RMS Fixed C++ declaration and cast problems + 31-Mar-05 RMS Fixed inaccuracies in error reporting + 18-Mar-05 RMS Added attached test to detach routine + 10-Sep-04 RMS Cloned from pdp10_tu.c 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 + 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. @@ -50,11 +51,11 @@ #elif defined (VM_PDP11) #include "pdp11_defs.h" -#define DEV_DIS_INIT DEV_DIS +#define DEV_DIS_INIT DEV_DIS #elif defined (VM_VAX) #include "vax_defs.h" -#define DEV_DIS_INIT 0 +#define DEV_DIS_INIT 0 #if (!UNIBUS) #error "Qbus not supported!" #endif @@ -62,174 +63,174 @@ #endif #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 */ -#define DEV_V_TM03 (DEV_V_FFUF + 0) /* TM02/TM03 */ -#define DEV_TM03 (1 << DEV_V_TM03) -#define UNIT_V_TYPE (MTUF_V_UF + 0) -#define UNIT_M_TYPE 03 -#define UNIT_TYPE (UNIT_M_TYPE << UNIT_V_TYPE) -#define UNIT_TE16 (0 << UNIT_V_TYPE) -#define UNIT_TU45 (1 << UNIT_V_TYPE) -#define UNIT_TU77 (2 << UNIT_V_TYPE) -#define GET_TYPE(x) (((x) >> UNIT_V_TYPE) & UNIT_M_TYPE) +#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 */ +#define DEV_V_TM03 (DEV_V_FFUF + 0) /* TM02/TM03 */ +#define DEV_TM03 (1 << DEV_V_TM03) +#define UNIT_V_TYPE (MTUF_V_UF + 0) +#define UNIT_M_TYPE 03 +#define UNIT_TYPE (UNIT_M_TYPE << UNIT_V_TYPE) +#define UNIT_TE16 (0 << UNIT_V_TYPE) +#define UNIT_TU45 (1 << UNIT_V_TYPE) +#define UNIT_TU77 (2 << UNIT_V_TYPE) +#define GET_TYPE(x) (((x) >> UNIT_V_TYPE) & UNIT_M_TYPE) /* CS1 - offset 0 */ -#define CS1_OF 0 -#define CS1_GO CSR_GO /* go */ -#define CS1_V_FNC 1 /* function pos */ -#define CS1_M_FNC 037 /* function mask */ -#define CS1_N_FNC (CS1_M_FNC + 1) -#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_RW 077 -#define GET_FNC(x) (((x) >> CS1_V_FNC) & CS1_M_FNC) +#define CS1_OF 0 +#define CS1_GO CSR_GO /* go */ +#define CS1_V_FNC 1 /* function pos */ +#define CS1_M_FNC 037 /* function mask */ +#define CS1_N_FNC (CS1_M_FNC + 1) +#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_RW 077 +#define GET_FNC(x) (((x) >> CS1_V_FNC) & CS1_M_FNC) /* TUFS - formatter status - offset 1 + indicates kept in drive status ^ indicates calculated on the fly */ -#define FS_OF 1 -#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_OF 1 +#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) +#define FS_DYN (FS_ERR | FS_PIP | FS_MOL | FS_WRL | FS_EOT | \ + FS_RDY | FS_PE | FS_BOT) /* TUER - error register - offset 2 */ -#define ER_OF 2 -#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 */ +#define ER_OF 2 +#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 */ /* TUMR - maintenance register - offset 03 */ -#define MR_OF 3 -#define MR_RW 0177637 /* read/write */ +#define MR_OF 3 +#define MR_RW 0177637 /* read/write */ /* TUAS - attention summary - offset 4 */ -#define AS_OF 4 -#define AS_U0 0000001 /* unit 0 flag */ +#define AS_OF 4 +#define AS_U0 0000001 /* unit 0 flag */ /* TUFC - offset 5 */ -#define FC_OF 5 +#define FC_OF 5 /* TUDT - drive type - offset 6 */ -#define DT_OF 6 -#define DT_NSA 0100000 /* not sect addr */ -#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_TU16 0000011 /* TE16 */ -#define DT_TU45 0000012 /* TU45 */ -#define DT_TU77 0000014 /* TU77 */ +#define DT_OF 6 +#define DT_NSA 0100000 /* not sect addr */ +#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_TU16 0000011 /* TE16 */ +#define DT_TU45 0000012 /* TU45 */ +#define DT_TU77 0000014 /* TU77 */ /* TUCC - check character, read only - offset 7 */ -#define CC_OF 7 -#define CC_MBZ 0177000 /* must be zero */ +#define CC_OF 7 +#define CC_MBZ 0177000 /* must be zero */ /* TUSN - serial number - offset 8 */ -#define SN_OF 8 +#define SN_OF 8 /* TUTC - tape control register - offset 9 */ -#define TC_OF 9 -#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_STD 014 /* standard */ -#define TC_CDUMP 015 /* core dump */ -#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 TC_RIP ((TC_800 << TC_V_DEN) | (TC_STD << TC_V_FMT)) -#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) - -int32 tucs1 = 0; /* control/status 1 */ -int32 tufc = 0; /* frame count */ -int32 tufs = 0; /* formatter status */ -int32 tuer = 0; /* error status */ -int32 tucc = 0; /* check character */ -int32 tumr = 0; /* maint register */ -int32 tutc = 0; /* tape control */ -int32 tu_time = 10; /* record latency */ -int32 tu_stopioe = 1; /* stop on error */ -static uint8 *xbuf = NULL; /* xfer buffer */ +#define TC_OF 9 +#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_STD 014 /* standard */ +#define TC_CDUMP 015 /* core dump */ +#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 TC_RIP ((TC_800 << TC_V_DEN) | (TC_STD << TC_V_FMT)) +#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) + +int32 tucs1 = 0; /* control/status 1 */ +int32 tufc = 0; /* frame count */ +int32 tufs = 0; /* formatter status */ +int32 tuer = 0; /* error status */ +int32 tucc = 0; /* check character */ +int32 tumr = 0; /* maint register */ +int32 tutc = 0; /* tape control */ +int32 tu_time = 10; /* record latency */ +int32 tu_stopioe = 1; /* stop on error */ +static uint8 *xbuf = NULL; /* xfer buffer */ static uint16 *wbuf = NULL; -static int32 den_test[8] = { /* valid densities */ - 1, 1, 1, 1, 1, 0, 0, 0 }; /* 0-3 = 800, 4 = 1600 */ -static int32 fmt_test[16] = { /* fmt valid */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0 }; +static int32 fmt_test[16] = { /* fmt valid */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0 + }; static int32 dt_map[3] = { DT_TU16, DT_TU45, DT_TU77 }; static char *tu_fname[CS1_N_FNC] = { - "NOP", "UNLD", "2", "REW", "FCLR", "5", "6", "7", - "RIP", "11", "ERASE", "WREOF", "SPCF", "SPCR", "16", "17", - "20", "21", "22", "23", "WRCHKF", "25", "26", "WRCHKR", - "WRITE", "31", "32", "33", "READF", "35", "36" "READR" }; + "NOP", "UNLD", "2", "REW", "FCLR", "5", "6", "7", + "RIP", "11", "ERASE", "WREOF", "SPCF", "SPCR", "16", "17", + "20", "21", "22", "23", "WRCHKF", "25", "26", "WRCHKR", + "WRITE", "31", "32", "33", "READF", "35", "36" "READR" + }; extern int32 sim_switches; extern FILE *sim_deb; @@ -252,162 +253,189 @@ t_stat tu_map_err (int32 drv, t_stat st, t_bool qdt); /* TU data structures - tu_dev TU device descriptor - tu_unit TU unit list - tu_reg TU register list - tu_mod TU modifier list + tu_dev TU device descriptor + tu_unit TU unit list + tu_reg TU register list + tu_mod TU modifier list */ DIB tu_dib = { MBA_TU, 0, &tu_mbrd, &tu_mbwr,0, 0, 0, { &tu_abort } }; 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) } }; + { 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[] = { - { GRDATA (CS1, tucs1, DEV_RDX, 6, 0) }, - { GRDATA (FC, tufc, DEV_RDX, 16, 0) }, - { GRDATA (FS, tufs, DEV_RDX, 16, 0) }, - { GRDATA (ER, tuer, DEV_RDX, 16, 0) }, - { GRDATA (CC, tucc, DEV_RDX, 16, 0) }, - { GRDATA (MR, tumr, DEV_RDX, 16, 0) }, - { GRDATA (TC, tutc, DEV_RDX, 16, 0) }, - { FLDATA (STOP_IOE, tu_stopioe, 0) }, - { DRDATA (TIME, tu_time, 24), PV_LEFT }, - { URDATA (UST, tu_unit[0].USTAT, DEV_RDX, 17, 0, TU_NUMDR, 0) }, - { URDATA (POS, tu_unit[0].pos, 10, T_ADDR_W, 0, - TU_NUMDR, PV_LEFT | REG_RO) }, - { NULL } }; + { GRDATA (CS1, tucs1, DEV_RDX, 6, 0) }, + { GRDATA (FC, tufc, DEV_RDX, 16, 0) }, + { GRDATA (FS, tufs, DEV_RDX, 16, 0) }, + { GRDATA (ER, tuer, DEV_RDX, 16, 0) }, + { GRDATA (CC, tucc, DEV_RDX, 16, 0) }, + { GRDATA (MR, tumr, DEV_RDX, 16, 0) }, + { GRDATA (TC, tutc, DEV_RDX, 16, 0) }, + { FLDATA (STOP_IOE, tu_stopioe, 0) }, + { DRDATA (TIME, tu_time, 24), PV_LEFT }, + { URDATA (UST, tu_unit[0].USTAT, DEV_RDX, 17, 0, TU_NUMDR, 0) }, + { URDATA (POS, tu_unit[0].pos, 10, T_ADDR_W, 0, + TU_NUMDR, PV_LEFT | REG_RO) }, + { NULL } + }; MTAB tu_mod[] = { - { MTAB_XTD|MTAB_VDV, 0, "MASSBUS", "MASSBUS", NULL, &mba_show_num }, - { MTAB_XTD|MTAB_VDV, 0, "FORMATTER", "TM02", - &tu_set_fmtr, &tu_show_fmtr }, - { MTAB_XTD|MTAB_VDV, 1, NULL, "TM03", - &tu_set_fmtr, NULL }, - { MTUF_WLK, 0, "write enabled", "WRITEENABLED", NULL }, - { MTUF_WLK, MTUF_WLK, "write locked", "LOCKED", NULL }, - { UNIT_TYPE, UNIT_TE16, "TE16", "TE16", NULL }, - { UNIT_TYPE, UNIT_TU45, "TU45", "TU45", NULL }, - { UNIT_TYPE, UNIT_TU77, "TU77", "TU77", NULL }, - { MTAB_XTD|MTAB_VUN, 0, "FORMAT", "FORMAT", - &sim_tape_set_fmt, &sim_tape_show_fmt, NULL }, - { 0 } }; + { MTAB_XTD|MTAB_VDV, 0, "MASSBUS", "MASSBUS", NULL, &mba_show_num }, + { MTAB_XTD|MTAB_VDV, 0, "FORMATTER", "TM02", + &tu_set_fmtr, &tu_show_fmtr }, + { MTAB_XTD|MTAB_VDV, 1, NULL, "TM03", + &tu_set_fmtr, NULL }, + { MTUF_WLK, 0, "write enabled", "WRITEENABLED", NULL }, + { MTUF_WLK, MTUF_WLK, "write locked", "LOCKED", NULL }, + { UNIT_TYPE, UNIT_TE16, "TE16", "TE16", NULL }, + { UNIT_TYPE, UNIT_TU45, "TU45", "TU45", NULL }, + { UNIT_TYPE, UNIT_TU77, "TU77", "TU77", NULL }, + { MTAB_XTD|MTAB_VUN, 0, "FORMAT", "FORMAT", + &sim_tape_set_fmt, &sim_tape_show_fmt, NULL }, + { 0 } + }; DEVICE tu_dev = { - "TU", tu_unit, tu_reg, tu_mod, - TU_NUMDR, 10, 31, 1, DEV_RDX, 8, - NULL, NULL, &tu_reset, - &tu_boot, &tu_attach, &tu_detach, - &tu_dib, DEV_MBUS | DEV_UBUS | DEV_QBUS | DEV_DEBUG | DEV_DISABLE | DEV_DIS_INIT }; - + "TU", tu_unit, tu_reg, tu_mod, + TU_NUMDR, 10, 31, 1, DEV_RDX, 8, + NULL, NULL, &tu_reset, + &tu_boot, &tu_attach, &tu_detach, + &tu_dib, DEV_MBUS | DEV_UBUS | DEV_QBUS | DEV_DEBUG | DEV_DISABLE | DEV_DIS_INIT + }; + /* Massbus register read */ t_stat tu_mbrd (int32 *data, int32 ofs, int32 fmtr) { int32 drv; -if (fmtr != 0) { /* only one fmtr */ - *data = 0; - return MBE_NXD; - } -drv = GET_DRV (tutc); /* get current unit */ -tu_update_fs (0, drv); /* update status */ +if (fmtr != 0) { /* only one fmtr */ + *data = 0; + return MBE_NXD; + } +drv = GET_DRV (tutc); /* get current unit */ +tu_update_fs (0, drv); /* update status */ + +switch (ofs) { /* decode offset */ + + case CS1_OF: /* MTCS1 */ + *data = tucs1 & CS1_RW; + break; + + case FC_OF: /* MTFC */ + *data = tufc; + break; + + case FS_OF: /* MTFS */ + *data = tufs & 0177777; /* mask off rewind */ + break; + + case ER_OF: /* MTER */ + *data = tuer; + break; + + case AS_OF: /* MTAS */ + *data = (tufs & FS_ATA)? AS_U0: 0; + break; + + case CC_OF: /* MTCC */ + *data = tucc = tucc & ~CC_MBZ; + break; + + case MR_OF: /* MTMR */ + *data = tumr; + break; + + case DT_OF: /* MTDT */ + *data = DT_NSA | DT_TAPE | /* fmtr flags */ + ((tu_dev.flags & DEV_TM03)? DT_TM03: 0); + if (tu_unit[drv].flags & UNIT_DIS) *data |= DT_OFF; + else *data |= DT_PRES | dt_map[GET_TYPE (tu_unit[drv].flags)]; + break; + + case SN_OF: /* MTSN */ + *data = (tu_unit[drv].flags & UNIT_DIS)? 0: 040 | (drv + 1); + break; + + case TC_OF: /* MTTC */ + *data = tutc = tutc & ~TC_MBZ; + break; + + default: /* all others */ + return MBE_NXR; + } -switch (ofs) { /* decode offset */ -case CS1_OF: /* MTCS1 */ - *data = tucs1 & CS1_RW; - break; -case FC_OF: /* MTFC */ - *data = tufc; - break; -case FS_OF: /* MTFS */ - *data = tufs & 0177777; /* mask off rewind */ - break; -case ER_OF: /* MTER */ - *data = tuer; - break; -case AS_OF: /* MTAS */ - *data = (tufs & FS_ATA)? AS_U0: 0; - break; -case CC_OF: /* MTCC */ - *data = tucc = tucc & ~CC_MBZ; - break; -case MR_OF: /* MTMR */ - *data = tumr; - break; -case DT_OF: /* MTDT */ - *data = DT_NSA | DT_TAPE | /* fmtr flags */ - ((tu_dev.flags & DEV_TM03)? DT_TM03: 0); - if (tu_unit[drv].flags & UNIT_DIS) *data |= DT_OFF; - else *data |= DT_PRES | dt_map[GET_TYPE (tu_unit[drv].flags)]; - break; -case SN_OF: /* MTSN */ - *data = (tu_unit[drv].flags & UNIT_DIS)? 0: 040 | (drv + 1); - break; -case TC_OF: /* MTTC */ - *data = tutc = tutc & ~TC_MBZ; - break; -default: /* all others */ - return MBE_NXR; } return SCPE_OK; } - + /* Massbus register write */ t_stat tu_mbwr (int32 data, int32 ofs, int32 fmtr) { int32 drv; -if (fmtr != 0) return MBE_NXD; /* only one fmtr */ -drv = GET_DRV (tutc); /* get current unit */ +if (fmtr != 0) return MBE_NXD; /* only one fmtr */ +drv = GET_DRV (tutc); /* get current unit */ + +switch (ofs) { /* decode PA<4:1> */ + + case CS1_OF: /* MTCS1 */ + if (tucs1 & CS1_GO) tu_set_er (ER_RMR); + else { + tucs1 = data & CS1_RW; + if (tucs1 & CS1_GO) return tu_go (drv); + } + break; + + case FC_OF: /* MTFC */ + if (tucs1 & CS1_GO) tu_set_er (ER_RMR); + else { + tufc = data; + tutc = tutc | TC_FCS; /* set fc flag */ + } + break; + + case AS_OF: /* MTAS */ + tu_clr_as (data); + break; + + case MR_OF: /* MTMR */ + tumr = (tumr & ~MR_RW) | (data & MR_RW); + break; + + case TC_OF: /* MTTC */ + if (tucs1 & CS1_GO) tu_set_er (ER_RMR); + else { + tutc = (tutc & ~TC_RW) | (data & TC_RW) | TC_SAC; + drv = GET_DRV (tutc); + } + break; + + case FS_OF: /* MTFS */ + case ER_OF: /* MTER */ + case CC_OF: /* MTCC */ + case DT_OF: /* MTDT */ + case SN_OF: /* MTSN */ + if (tucs1 & CS1_GO) tu_set_er (ER_RMR); + break; /* read only */ + + default: /* all others */ + return MBE_NXR; + } /* end switch */ -switch (ofs) { /* decode PA<4:1> */ -case CS1_OF: /* MTCS1 */ - if (tucs1 & CS1_GO) tu_set_er (ER_RMR); - else { - tucs1 = data & CS1_RW; - if (tucs1 & CS1_GO) return tu_go (drv); - } - break; -case FC_OF: /* MTFC */ - if (tucs1 & CS1_GO) tu_set_er (ER_RMR); - else { - tufc = data; - tutc = tutc | TC_FCS; /* set fc flag */ - } - break; -case AS_OF: /* MTAS */ - tu_clr_as (data); - break; -case MR_OF: /* MTMR */ - tumr = (tumr & ~MR_RW) | (data & MR_RW); - break; -case TC_OF: /* MTTC */ - if (tucs1 & CS1_GO) tu_set_er (ER_RMR); - else { - tutc = (tutc & ~TC_RW) | (data & TC_RW) | TC_SAC; - drv = GET_DRV (tutc); } - break; -case FS_OF: /* MTFS */ -case ER_OF: /* MTER */ -case CC_OF: /* MTCC */ -case DT_OF: /* MTDT */ -case SN_OF: /* MTSN */ - if (tucs1 & CS1_GO) tu_set_er (ER_RMR); - break; /* read only */ -default: /* all others */ - return MBE_NXR; } /* end switch */ tu_update_fs (0, drv); return SCPE_OK; } - + /* New magtape command */ t_stat tu_go (int32 drv) @@ -415,112 +443,125 @@ t_stat 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 */ +fnc = GET_FNC (tucs1); /* get function */ +den = GET_DEN (tutc); /* get density */ +uptr = tu_dev.units + drv; /* get unit */ if (DEBUG_PRS (tu_dev)) fprintf (sim_deb, - ">>TU%d STRT: fnc=%s, fc=%06o, fs=%06o, er=%06o, pos=%d\n", - drv, tu_fname[fnc], tufc, tufs, tuer, uptr->pos); + ">>TU%d STRT: fnc=%s, fc=%06o, fs=%06o, er=%06o, pos=%d\n", + drv, tu_fname[fnc], tufc, tufs, tuer, uptr->pos); -if ((fnc != FNC_FCLR) && /* not clear & err */ - ((tufs & FS_ERR) || sim_is_active (uptr))) { /* or in motion? */ - tu_set_er (ER_ILF); /* set err */ - tucs1 = tucs1 & ~CS1_GO; /* clear go */ - tu_update_fs (FS_ATA, drv); /* set attn */ - return MBE_GOE; } -tu_clr_as (AS_U0); /* clear ATA */ -tutc = tutc & ~TC_SAC; /* clear addr change */ +if ((fnc != FNC_FCLR) && /* not clear & err */ + ((tufs & FS_ERR) || sim_is_active (uptr))) { /* or in motion? */ + tu_set_er (ER_ILF); /* set err */ + tucs1 = tucs1 & ~CS1_GO; /* clear go */ + tu_update_fs (FS_ATA, drv); /* set attn */ + return MBE_GOE; + } +tu_clr_as (AS_U0); /* clear ATA */ +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_ERR); - sim_cancel (uptr); /* reset drive */ - uptr->USTAT = 0; -case FNC_NOP: - tucs1 = tucs1 & ~CS1_GO; /* no operation */ - return SCPE_OK; +switch (fnc) { /* case on function */ -case FNC_RIP: /* read-in preset */ - tutc = TC_RIP; /* set tutc */ - sim_tape_rewind (&tu_unit[0]); /* rewind unit 0 */ - tu_unit[0].USTAT = 0; - tucs1 = tucs1 & ~CS1_GO; - tufs = tufs & ~FS_TMK; - return SCPE_OK; + 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_ERR); + sim_cancel (uptr); /* reset drive */ + uptr->USTAT = 0; + case FNC_NOP: + tucs1 = tucs1 & ~CS1_GO; /* no operation */ + return SCPE_OK; -case FNC_UNLOAD: /* unload */ - if ((uptr->flags & UNIT_ATT) == 0) { /* unattached? */ - tu_set_er (ER_UNS); - break; } - detach_unit (uptr); - uptr->USTAT = FS_REW; - sim_activate (uptr, tu_time); - tucs1 = tucs1 & ~CS1_GO; - tufs = tufs & ~FS_TMK; - return SCPE_OK; + case FNC_RIP: /* read-in preset */ + tutc = TC_RIP; /* set tutc */ + sim_tape_rewind (&tu_unit[0]); /* rewind unit 0 */ + tu_unit[0].USTAT = 0; + tucs1 = tucs1 & ~CS1_GO; + tufs = tufs & ~FS_TMK; + return SCPE_OK; -case FNC_REWIND: - if ((uptr->flags & UNIT_ATT) == 0) { /* unattached? */ - tu_set_er (ER_UNS); - break; } - uptr->USTAT = FS_PIP | FS_REW; - sim_activate (uptr, tu_time); - tucs1 = tucs1 & ~CS1_GO; - tufs = tufs & ~FS_TMK; - return SCPE_OK; + case FNC_UNLOAD: /* unload */ + if ((uptr->flags & UNIT_ATT) == 0) { /* unattached? */ + tu_set_er (ER_UNS); + break; + } + detach_unit (uptr); + uptr->USTAT = FS_REW; + sim_activate (uptr, tu_time); + tucs1 = tucs1 & ~CS1_GO; + tufs = tufs & ~FS_TMK; + return SCPE_OK; -case FNC_SPACEF: - space_test = FS_EOT; -case FNC_SPACER: - if ((uptr->flags & UNIT_ATT) == 0) { /* unattached? */ - tu_set_er (ER_UNS); - break; } - if ((tufs & space_test) || ((tutc & TC_FCS) == 0)) { - tu_set_er (ER_NXF); - break; } - uptr->USTAT = FS_PIP; - goto GO_XFER; + case FNC_REWIND: + if ((uptr->flags & UNIT_ATT) == 0) { /* unattached? */ + tu_set_er (ER_UNS); + break; + } + uptr->USTAT = FS_PIP | FS_REW; + sim_activate (uptr, tu_time); + tucs1 = tucs1 & ~CS1_GO; + tufs = tufs & ~FS_TMK; + return SCPE_OK; -case FNC_WCHKR: /* wchk = read */ -case FNC_READR: /* read rev */ - if (tufs & FS_BOT) { /* beginning of tape? */ - tu_set_er (ER_NXF); - break; } - goto DATA_XFER; + case FNC_SPACEF: + space_test = FS_EOT; + case FNC_SPACER: + if ((uptr->flags & UNIT_ATT) == 0) { /* unattached? */ + tu_set_er (ER_UNS); + break; + } + if ((tufs & space_test) || ((tutc & TC_FCS) == 0)) { + tu_set_er (ER_NXF); + break; + } + uptr->USTAT = FS_PIP; + goto GO_XFER; -case FNC_WRITE: /* write */ - if (((tutc & TC_FCS) == 0) || /* frame cnt = 0? */ - ((den == TC_800) && (tufc > 0777765))) { /* NRZI, fc < 13? */ - tu_set_er (ER_NXF); - break; } -case FNC_WREOF: /* write tape mark */ -case FNC_ERASE: /* erase */ - if (sim_tape_wrp (uptr)) { /* write locked? */ - tu_set_er (ER_NXF); - break; } -case FNC_WCHKF: /* wchk = read */ -case FNC_READF: /* read */ -DATA_XFER: - if ((uptr->flags & UNIT_ATT) == 0) { /* unattached? */ - tu_set_er (ER_UNS); - break; } - if (fmt_test[GET_FMT (tutc)] == 0) { /* invalid format? */ - tu_set_er (ER_FER); - break; } - if (uptr->UDENS == UD_UNK) uptr->UDENS = den; /* set dens */ - uptr->USTAT = 0; -GO_XFER: - tufs = tufs & ~(FS_TMK | FS_ID); /* clear eof, id */ - sim_activate (uptr, tu_time); - return SCPE_OK; + case FNC_WCHKR: /* wchk = read */ + case FNC_READR: /* read rev */ + if (tufs & FS_BOT) { /* beginning of tape? */ + tu_set_er (ER_NXF); + break; + } + goto DATA_XFER; -default: /* all others */ - tu_set_er (ER_ILF); /* not supported */ - break; } /* end case function */ -tucs1 = tucs1 & ~CS1_GO; /* clear go */ -tu_update_fs (FS_ATA, drv); /* set attn */ + case FNC_WRITE: /* write */ + if (((tutc & TC_FCS) == 0) || /* frame cnt = 0? */ + ((den == TC_800) && (tufc > 0777765))) { /* NRZI, fc < 13? */ + tu_set_er (ER_NXF); + break; + } + case FNC_WREOF: /* write tape mark */ + case FNC_ERASE: /* erase */ + if (sim_tape_wrp (uptr)) { /* write locked? */ + tu_set_er (ER_NXF); + break; + } + case FNC_WCHKF: /* wchk = read */ + case FNC_READF: /* read */ + DATA_XFER: + if ((uptr->flags & UNIT_ATT) == 0) { /* unattached? */ + tu_set_er (ER_UNS); + break; + } + if (fmt_test[GET_FMT (tutc)] == 0) { /* invalid format? */ + tu_set_er (ER_FER); + break; + } + if (uptr->UDENS == UD_UNK) uptr->UDENS = den; /* set dens */ + uptr->USTAT = 0; + GO_XFER: + tufs = tufs & ~(FS_TMK | FS_ID); /* clear eof, id */ + sim_activate (uptr, tu_time); + return SCPE_OK; + + default: /* all others */ + tu_set_er (ER_ILF); /* not supported */ + break; + } /* end case function */ + +tucs1 = tucs1 & ~CS1_GO; /* clear go */ +tu_update_fs (FS_ATA, drv); /* set attn */ return MBE_GOE; } @@ -530,7 +571,7 @@ t_stat tu_abort (void) { return tu_reset (&tu_dev); } - + /* Unit service Complete movement or data transfer command @@ -545,164 +586,169 @@ int32 fc, drv; t_mtrlnt i, 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 */ - tu_update_fs (FS_ATA | FS_SSC, drv); - return SCPE_OK; } +drv = (int32) (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 */ + tu_update_fs (FS_ATA | FS_SSC, drv); + return SCPE_OK; + } -fnc = GET_FNC (tucs1); /* get command */ -fmt = GET_FMT (tutc); /* get format */ -fc = 0200000 - tufc; /* get frame count */ -uptr->USTAT = 0; /* clear status */ +fnc = GET_FNC (tucs1); /* get command */ +fmt = GET_FMT (tutc); /* get format */ +fc = 0200000 - tufc; /* get frame count */ +uptr->USTAT = 0; /* clear status */ if ((uptr->flags & UNIT_ATT) == 0) { - tu_set_er (ER_UNS); /* set formatter error */ - if (fnc >= FNC_XFER) mba_set_don (tu_dib.ba); - tu_update_fs (FS_ATA, drv); - return (tu_stopioe? SCPE_UNATT: SCPE_OK); - } -switch (fnc) { /* case on function */ + tu_set_er (ER_UNS); /* set formatter error */ + if (fnc >= FNC_XFER) mba_set_don (tu_dib.ba); + tu_update_fs (FS_ATA, drv); + return (tu_stopioe? SCPE_UNATT: SCPE_OK); + } +switch (fnc) { /* case on function */ /* 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 (drv, st, 0); /* map error */ - break; } - } - while (tufc != 0); - if (tufc) tu_set_er (ER_FCE); - else tutc = tutc & ~TC_FCS; - break; + 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 (drv, st, 0); /* map error */ + break; + } + } while (tufc != 0); + if (tufc) tu_set_er (ER_FCE); + else tutc = tutc & ~TC_FCS; + 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 (drv, st, 0); /* map error */ - break; } - } - while (tufc != 0); - if (tufc) tu_set_er (ER_FCE); - else tutc = tutc & ~TC_FCS; - 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 (drv, st, 0); /* map error */ + break; + } + } while (tufc != 0); + if (tufc) tu_set_er (ER_FCE); + else tutc = tutc & ~TC_FCS; + break; -case FNC_WREOF: /* write end of file */ - if (st = sim_tape_wrtmk (uptr)) /* write tmk, err? */ - r = tu_map_err (drv, st, 0); /* map error */ - break; + case FNC_WREOF: /* write end of file */ + if (st = sim_tape_wrtmk (uptr)) /* write tmk, err? */ + r = tu_map_err (drv, st, 0); /* map error */ + break; + + case FNC_ERASE: + if (sim_tape_wrp (uptr)) /* write protected? */ + r = tu_map_err (drv, MTSE_WRP, 0); /* map error */ + break; -case FNC_ERASE: - if (sim_tape_wrp (uptr)) /* write protected? */ - r = tu_map_err (drv, MTSE_WRP, 0); /* map error */ - break; - /* Unit service - data transfer commands */ -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 */ - if (st = sim_tape_rdrecf (uptr, xbuf, &tbc, MT_MAXFR)) { /* read fwd */ - r = tu_map_err (drv, st, 1); /* map error */ - break; } /* done */ - for (i = tbc; i < tbc + 4; i++) xbuf[i] = 0; /* pad with 0's */ - if (fmt == TC_CDUMP) { /* core dump? */ - for (i = j = 0; i < tbc; i = i + 4) { - wbuf[j++] = ((uint16) xbuf[i] & 0xF) | - (((uint16) (xbuf[i + 1] & 0xF)) << 4) | - (((uint16) (xbuf[i + 2] & 0xF)) << 8) | - (((uint16) (xbuf[i + 3] & 0xf)) << 12); - } - xbc = (tbc + 1) >> 1; - } - else { /* standard */ - for (i = j = 0; i < tbc; i = i + 2) { - wbuf[j++] = ((uint16) xbuf[i]) | - (((uint16) xbuf[i + 1]) << 8); - } - xbc = tbc; - } - if (mba_get_bc (tu_dib.ba) > xbc) /* record short? */ - tu_set_er (ER_FCE); /* set FCE, ATN */ - if (fnc == FNC_WCHKF) mba_chbufW (tu_dib.ba, xbc, wbuf); - else mba_wrbufW (tu_dib.ba, xbc, wbuf); - tufc = tbc & 0177777; - break; + 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 */ + if (st = sim_tape_rdrecf (uptr, xbuf, &tbc, MT_MAXFR)) { /* read fwd */ + r = tu_map_err (drv, st, 1); /* map error */ + break; /* done */ + } + for (i = tbc; i < tbc + 4; i++) xbuf[i] = 0; /* pad with 0's */ + if (fmt == TC_CDUMP) { /* core dump? */ + for (i = j = 0; i < tbc; i = i + 4) { + wbuf[j++] = ((uint16) xbuf[i] & 0xF) | + (((uint16) (xbuf[i + 1] & 0xF)) << 4) | + (((uint16) (xbuf[i + 2] & 0xF)) << 8) | + (((uint16) (xbuf[i + 3] & 0xf)) << 12); + } + xbc = (tbc + 1) >> 1; + } + else { /* standard */ + for (i = j = 0; i < tbc; i = i + 2) { + wbuf[j++] = ((uint16) xbuf[i]) | + (((uint16) xbuf[i + 1]) << 8); + } + xbc = tbc; + } + if (mba_get_bc (tu_dib.ba) > xbc) /* record short? */ + tu_set_er (ER_FCE); /* set FCE, ATN */ + if (fnc == FNC_WCHKF) mba_chbufW (tu_dib.ba, xbc, wbuf); + else mba_wrbufW (tu_dib.ba, xbc, wbuf); + tufc = tbc & 0177777; + break; -case FNC_WRITE: /* write */ - xbc = mba_rdbufW (tu_dib.ba, fc, wbuf); /* read buffer */ - if (xbc == 0) break; /* anything?? */ - if (fmt == TC_CDUMP) { /* core dump? */ - for (i = j = 0; j < xbc; j = j + 1) { - xbuf[i++] = wbuf[j] & 0xF; - xbuf[i++] = (wbuf[j] >> 4) & 0xF; - xbuf[i++] = (wbuf[j] >> 8) & 0xF; - xbuf[i++] = (wbuf[j] >> 12) & 0xF; - } - tbc = (xbc + 1) >> 1; - } - else { /* standard */ - for (i = j = 0; j < xbc; j = j + 1) { - xbuf[i++] = wbuf[j] & 0377; - xbuf[i++] = (wbuf[j] >> 8) & 0377; } - tbc = xbc; - } - if (st = sim_tape_wrrecf (uptr, xbuf, tbc)) /* write rec, err? */ - r = tu_map_err (drv, st, 1); /* map error */ - else { - tufc = (tufc + tbc) & 0177777; - if (tufc == 0) tutc = tutc & ~TC_FCS; - } - break; + case FNC_WRITE: /* write */ + xbc = mba_rdbufW (tu_dib.ba, fc, wbuf); /* read buffer */ + if (xbc == 0) break; /* anything?? */ + if (fmt == TC_CDUMP) { /* core dump? */ + for (i = j = 0; j < xbc; j = j + 1) { + xbuf[i++] = wbuf[j] & 0xF; + xbuf[i++] = (wbuf[j] >> 4) & 0xF; + xbuf[i++] = (wbuf[j] >> 8) & 0xF; + xbuf[i++] = (wbuf[j] >> 12) & 0xF; + } + tbc = (xbc + 1) >> 1; + } + else { /* standard */ + for (i = j = 0; j < xbc; j = j + 1) { + xbuf[i++] = wbuf[j] & 0377; + xbuf[i++] = (wbuf[j] >> 8) & 0377; + } + tbc = xbc; + } + if (st = sim_tape_wrrecf (uptr, xbuf, tbc)) /* write rec, err? */ + r = tu_map_err (drv, st, 1); /* map error */ + else { + tufc = (tufc + tbc) & 0177777; + if (tufc == 0) tutc = tutc & ~TC_FCS; + } + break; -case FNC_READR: /* read reverse */ -case FNC_WCHKR: /* wcheck = read */ - tufc = 0; /* clear frame count */ - if (st = sim_tape_rdrecr (uptr, xbuf + 4, &tbc, MT_MAXFR)) { /* read rev */ - r = tu_map_err (drv, st, 1); /* map error */ - break; } /* done */ - for (i = 0; i < 4; i++) xbuf[i] = 0; /* pad with 0's */ - if (fmt == TC_CDUMP) { /* core dump? */ - for (i = tbc + 3, j = 0; i > 3; i = i - 4) { - wbuf[j++] = ((uint16) xbuf[i] & 0xF) | - (((uint16) (xbuf[i - 1] & 0xF)) << 4) | - (((uint16) (xbuf[i - 2] & 0xF)) << 8) | - (((uint16) (xbuf[i - 3] & 0xf)) << 12); - } - xbc = (tbc + 1) >> 1; - } - else { /* standard */ - for (i = tbc + 3, j = 0; i > 3; i = i - 2) { - wbuf[j++] = ((uint16) xbuf[i]) | - (((uint16) xbuf[i - 1]) << 8); - } - xbc = tbc; - } - if (mba_get_bc (tu_dib.ba) > xbc) /* record short? */ - tu_set_er (ER_FCE); /* set FCE, ATN */ - if (fnc == FNC_WCHKR) mba_chbufW (tu_dib.ba, xbc, wbuf); - else mba_wrbufW (tu_dib.ba, xbc, wbuf); - tufc = tbc & 0177777; - break; - } /* end case */ + case FNC_READR: /* read reverse */ + case FNC_WCHKR: /* wcheck = read */ + tufc = 0; /* clear frame count */ + if (st = sim_tape_rdrecr (uptr, xbuf + 4, &tbc, MT_MAXFR)) { /* read rev */ + r = tu_map_err (drv, st, 1); /* map error */ + break; /* done */ + } + for (i = 0; i < 4; i++) xbuf[i] = 0; /* pad with 0's */ + if (fmt == TC_CDUMP) { /* core dump? */ + for (i = tbc + 3, j = 0; i > 3; i = i - 4) { + wbuf[j++] = ((uint16) xbuf[i] & 0xF) | + (((uint16) (xbuf[i - 1] & 0xF)) << 4) | + (((uint16) (xbuf[i - 2] & 0xF)) << 8) | + (((uint16) (xbuf[i - 3] & 0xf)) << 12); + } + xbc = (tbc + 1) >> 1; + } + else { /* standard */ + for (i = tbc + 3, j = 0; i > 3; i = i - 2) { + wbuf[j++] = ((uint16) xbuf[i]) | + (((uint16) xbuf[i - 1]) << 8); + } + xbc = tbc; + } + if (mba_get_bc (tu_dib.ba) > xbc) /* record short? */ + tu_set_er (ER_FCE); /* set FCE, ATN */ + if (fnc == FNC_WCHKR) mba_chbufW (tu_dib.ba, xbc, wbuf); + else mba_wrbufW (tu_dib.ba, xbc, wbuf); + tufc = tbc & 0177777; + break; + } /* end case */ -tucs1 = tucs1 & ~CS1_GO; /* clear go */ -if (fnc >= FNC_XFER) { /* data xfer? */ - mba_set_don (tu_dib.ba); /* set done */ - tu_update_fs (0, drv); } /* update fs */ -else tu_update_fs (FS_ATA, drv); /* no, set attn */ +tucs1 = tucs1 & ~CS1_GO; /* clear go */ +if (fnc >= FNC_XFER) { /* data xfer? */ + mba_set_don (tu_dib.ba); /* set done */ + tu_update_fs (0, drv); /* update fs */ + } +else tu_update_fs (FS_ATA, drv); /* no, set attn */ if (DEBUG_PRS (tu_dev)) fprintf (sim_deb, - ">>TU%d DONE: fnc=%s, fc=%06o, fs=%06o, er=%06o, pos=%d\n", - drv, tu_fname[fnc], tufc, tufs, tuer, uptr->pos); + ">>TU%d DONE: fnc=%s, fc=%06o, fs=%06o, er=%06o, pos=%d\n", + drv, tu_fname[fnc], tufc, tufs, tuer, uptr->pos); return SCPE_OK; } - + /* Set formatter error */ void tu_set_er (int32 flg) @@ -730,10 +776,11 @@ int32 act = sim_is_active (&tu_unit[drv]); tufs = (tufs & ~FS_DYN) | FS_FPR | flg; 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; } + 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; if (tufs && !act) tufs = tufs | FS_RDY; if (flg & FS_ATA) mba_upd_ata (tu_dib.ba, 1); @@ -745,42 +792,53 @@ return; t_stat tu_map_err (int32 drv, t_stat st, t_bool qdt) { switch (st) { -case MTSE_FMT: /* illegal fmt */ -case MTSE_UNATT: /* not attached */ - tu_set_er (ER_NXF); /* can't execute */ - if (qdt) mba_set_exc (tu_dib.ba); /* set exception */ - break; -case MTSE_TMK: /* end of file */ - tufs = tufs | FS_TMK; - tu_set_er (ER_FCE); /* also sets FCE */ - break; -case MTSE_IOERR: /* IO error */ - tu_set_er (ER_VPE); /* flag error */ - if (qdt) mba_set_exc (tu_dib.ba); /* set exception */ - return (tu_stopioe? SCPE_IOERR: SCPE_OK); -case MTSE_INVRL: /* invalid rec lnt */ - tu_set_er (ER_VPE); /* flag error */ - if (qdt) mba_set_exc (tu_dib.ba); /* set exception */ - return SCPE_MTRLNT; -case MTSE_RECE: /* record in error */ - tu_set_er (ER_CRC); /* set crc err */ - if (qdt) mba_set_exc (tu_dib.ba); /* set exception */ - break; -case MTSE_EOM: /* end of medium */ - tu_set_er (ER_OPI); /* incomplete */ - if (qdt) mba_set_exc (tu_dib.ba); /* set exception */ - break; -case MTSE_BOT: /* reverse into BOT */ - return SCPE_OK; -case MTSE_WRP: /* write protect */ - tu_set_er (ER_NXF); /* can't execute */ - if (qdt) mba_set_exc (tu_dib.ba); /* set exception */ - break; -default: /* unknown error */ - return SCPE_IERR; } + + case MTSE_FMT: /* illegal fmt */ + case MTSE_UNATT: /* not attached */ + tu_set_er (ER_NXF); /* can't execute */ + if (qdt) mba_set_exc (tu_dib.ba); /* set exception */ + break; + + case MTSE_TMK: /* end of file */ + tufs = tufs | FS_TMK; + tu_set_er (ER_FCE); /* also sets FCE */ + break; + + case MTSE_IOERR: /* IO error */ + tu_set_er (ER_VPE); /* flag error */ + if (qdt) mba_set_exc (tu_dib.ba); /* set exception */ + return (tu_stopioe? SCPE_IOERR: SCPE_OK); + + case MTSE_INVRL: /* invalid rec lnt */ + tu_set_er (ER_VPE); /* flag error */ + if (qdt) mba_set_exc (tu_dib.ba); /* set exception */ + return SCPE_MTRLNT; + + case MTSE_RECE: /* record in error */ + tu_set_er (ER_CRC); /* set crc err */ + if (qdt) mba_set_exc (tu_dib.ba); /* set exception */ + break; + + case MTSE_EOM: /* end of medium */ + tu_set_er (ER_OPI); /* incomplete */ + if (qdt) mba_set_exc (tu_dib.ba); /* set exception */ + break; + + case MTSE_BOT: /* reverse into BOT */ + return SCPE_OK; + + case MTSE_WRP: /* write protect */ + tu_set_er (ER_NXF); /* can't execute */ + if (qdt) mba_set_exc (tu_dib.ba); /* set exception */ + break; + + default: /* unknown error */ + return SCPE_IERR; + } + return SCPE_OK; } - + /* Reset routine */ t_stat tu_reset (DEVICE *dptr) @@ -792,16 +850,17 @@ tucs1 = 0; tufc = 0; tuer = 0; tufs = FS_FPR | FS_RDY; -if (sim_switches & SWMASK ('P')) tutc = 0; /* powerup? clr TC */ -else tutc = tutc & ~TC_FCS; /* no, clr */ -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 (sim_switches & SWMASK ('P')) tutc = 0; /* powerup? clr TC */ +else tutc = tutc & ~TC_FCS; /* no, clr */ +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 = (uint8 *) calloc (MT_MAXFR + 4, sizeof (uint8)); if (xbuf == NULL) return SCPE_MEM; -if (wbuf == NULL) wbuf = calloc ((MT_MAXFR + 4) >> 1, sizeof (uint16)); +if (wbuf == NULL) wbuf = (uint16 *) calloc ((MT_MAXFR + 4) >> 1, sizeof (uint16)); if (wbuf == NULL) return SCPE_MEM; return SCPE_OK; } @@ -815,11 +874,11 @@ 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 */ -flg = FS_ATA | FS_SSC; /* set attention */ -if (GET_DRV (tutc) == drv) flg = flg | FS_SAT; /* sel drv? set SAT */ -tu_update_fs (flg, drv); /* update status */ +uptr->USTAT = 0; /* clear unit status */ +uptr->UDENS = UD_UNK; /* unknown density */ +flg = FS_ATA | FS_SSC; /* set attention */ +if (GET_DRV (tutc) == drv) flg = flg | FS_SAT; /* sel drv? set SAT */ +tu_update_fs (flg, drv); /* update status */ return r; } @@ -829,9 +888,9 @@ t_stat tu_detach (UNIT* uptr) { int32 drv = uptr - tu_dev.units; -if (!(uptr->flags & UNIT_ATT)) return SCPE_OK; /* attached? */ -uptr->USTAT = 0; /* clear status flags */ -tu_update_fs (FS_ATA | FS_SSC, drv); /* update status */ +if (!(uptr->flags & UNIT_ATT)) return SCPE_OK; /* attached? */ +uptr->USTAT = 0; /* clear status flags */ +tu_update_fs (FS_ATA | FS_SSC, drv); /* update status */ return sim_tape_detach (uptr); } @@ -863,39 +922,39 @@ return SCPE_OK; #elif 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 (uint16)) +#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 (uint16)) static const uint16 boot_rom[] = { - 0046515, /* "MM" */ - 0012706, BOOT_START, /* mov #boot_start, sp */ - 0012700, 0000000, /* mov #unit, r0 */ - 0012701, 0172440, /* mov #TUCS1, r1 */ - 0012761, 0000040, 0000010, /* mov #CS2_CLR, 10(r1) ; reset */ - 0012711, 0000021, /* mov #RIP+GO, (r1) ; rip */ - 0010004, /* mov r0, r4 */ - 0052704, 0002300, /* bis #2300, r4 ; set den */ - 0010461, 0000032, /* mov r4, 32(r1) ; set unit */ - 0012761, 0177777, 0000006, /* mov #-1, 6(r1) ; set fc */ - 0012711, 0000031, /* mov #SPCF+GO, (r1) ; skip rec */ - 0105761, 0000012, /* tstb 12 (r1) ; fmtr rdy? */ - 0100375, /* bpl .-4 */ - 0012761, 0177000, 0000002, /* mov #-1000, 2(r1) ; set wc */ - 0005061, 0000004, /* clr 4(r1) ; clr ba */ - 0005061, 0000006, /* clr 6(r1) ; clr fc */ - 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 */ -}; + 0046515, /* "MM" */ + 0012706, BOOT_START, /* mov #boot_start, sp */ + 0012700, 0000000, /* mov #unit, r0 */ + 0012701, 0172440, /* mov #TUCS1, r1 */ + 0012761, 0000040, 0000010, /* mov #CS2_CLR, 10(r1) ; reset */ + 0012711, 0000021, /* mov #RIP+GO, (r1) ; rip */ + 0010004, /* mov r0, r4 */ + 0052704, 0002300, /* bis #2300, r4 ; set den */ + 0010461, 0000032, /* mov r4, 32(r1) ; set unit */ + 0012761, 0177777, 0000006, /* mov #-1, 6(r1) ; set fc */ + 0012711, 0000031, /* mov #SPCF+GO, (r1) ; skip rec */ + 0105761, 0000012, /* tstb 12 (r1) ; fmtr rdy? */ + 0100375, /* bpl .-4 */ + 0012761, 0177000, 0000002, /* mov #-1000, 2(r1) ; set wc */ + 0005061, 0000004, /* clr 4(r1) ; clr ba */ + 0005061, 0000006, /* clr 6(r1) ; clr fc */ + 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 tu_boot (int32 unitno, DEVICE *dptr) { diff --git a/PDP11/pdp11_uqssp.h b/PDP11/pdp11_uqssp.h index 77703740..e0e4ce11 100644 --- a/PDP11/pdp11_uqssp.h +++ b/PDP11/pdp11_uqssp.h @@ -1,6 +1,6 @@ /* pdp11_uqssp.h: Unibus/Qbus storage systems port definitions file - Copyright (c) 2001-2004, Robert M Supnik + Copyright (c) 2001-2005, Robert M Supnik Derived from work by Stephen F. Shirron Permission is hereby granted, free of charge, to any person obtaining a @@ -20,15 +20,15 @@ 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 + 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 + 30-Aug-02 RMS Added TMSCP support */ #ifndef _PDP11_UQSSP_H_ -#define _PDP11_UQSSP_H_ 0 +#define _PDP11_UQSSP_H_ 0 /* IP register - initialization and polling @@ -42,128 +42,128 @@ 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 */ +#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 */ +#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)) +#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) +#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 */ +#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) +#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 */ +#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 # */ +#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 */ +#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 */ +#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) +#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 */ - }; + 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 */ +#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_HDR_OFF -4 /* offset */ -#define UQ_HLNT 0 /* length */ -#define UQ_HCTC 1 /* credits, type, CID */ +#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 */ +#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_vh.c b/PDP11/pdp11_vh.c index 70dcb5e0..c62eb510 100644 --- a/PDP11/pdp11_vh.c +++ b/PDP11/pdp11_vh.c @@ -1,6 +1,6 @@ /* pdp11_vh.c: DHQ11 asynchronous terminal multiplexor simulator - Copyright (c) 2004, John A. Dundas III + Copyright (c) 2004-2005, John A. Dundas III Portions derived from work by Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a @@ -20,31 +20,32 @@ 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 + 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. - vh DHQ11 asynch multiplexor for SIMH + vh DHQ11 asynch multiplexor for SIMH - 12-Jun-04 RMS Repair MS2SIMH macro to avoid possible divide by - 0 bug. - 8-Jun-04 JAD Repair vh_dev initialization; remove unused - variables, cast to avoid conversion confusion. - 7-Jun-04 JAD Complete function prototypes of forward declarations. - Repair broken prototypes of vh_rd() and vh_wr(). - Explicitly size integer declarations. + 07-Jul-05 RMS Removed extraneous externs + 15-Jun-05 RMS Revised for new autoconfigure interface + Fixed bug in vector display routine + 12-Jun-04 RMS Repair MS2SIMH macro to avoid divide by 0 bug + 08-Jun-04 JAD Repair vh_dev initialization; remove unused + variables, cast to avoid conversion confusion + 07-Jun-04 JAD Complete function prototypes of forward declarations. + Repair broken prototypes of vh_rd() and vh_wr() + Explicitly size integer declarations 4-Jun-04 JAD Preliminary code: If operating in a PDP-11 Unibus - environment, force DHU mode. - 29-May-04 JAD Make certain RX.TIMER is within allowable range. - 25-May-04 JAD All time-based operations are scaled by tmxr_poll - units. - 23-May-04 JAD Change to fifo_get() and dq_tx_report() to avoid - gratuitous stack manipulation. - 20-May-04 JAD Made modem control and auto-hangup unit flags - 19-May-04 JAD Fix problem with modem status where the line number + environment, force DHU mode + 29-May-04 JAD Make certain RX.TIMER is within allowable range + 25-May-04 JAD All time-based operations are scaled by tmxr_poll units + 23-May-04 JAD Change to fifo_get() and dq_tx_report() to avoid + gratuitous stack manipulation + 20-May-04 JAD Made modem control and auto-hangup unit flags + 19-May-04 JAD Fix problem with modem status where the line number was not being included - 12-May-04 JAD Revised for updated tmxr interfaces - 28-Jan-04 JAD Original creation and testing + 12-May-04 JAD Revised for updated tmxr interfaces + 28-Jan-04 JAD Original creation and testing I/O Page Registers @@ -57,18 +58,16 @@ Priority: BR4 Rank: 32 */ - /* MANY constants needed! */ +/* MANY constants needed! */ #if defined (VM_VAX) #include "vax_defs.h" extern int32 int_req[IPL_HLVL]; -extern int32 int_vec[IPL_HLVL][32]; #endif #if defined (VM_PDP11) #include "pdp11_defs.h" extern int32 int_req[IPL_HLVL]; -extern int32 int_vec[IPL_HLVL][32]; extern int32 cpu_opt; #endif @@ -235,7 +234,7 @@ extern FILE *sim_log; #define LOOP_NONE (0) #define LOOP_H325 (1) #define LOOP_H3101 (2) /* p.2-13 DHQ manual */ - /* Local storage */ +/* Local storage */ static uint16 vh_csr[VH_MUXES] = { 0 }; /* CSRs */ static uint16 vh_timer[VH_MUXES] = { 1 }; /* controller timeout */ @@ -281,7 +280,7 @@ static TMLN vh_ldsc[VH_MUXES * VH_LINES] = { 0 }; static TMXR vh_desc = { VH_MUXES * VH_LINES, 0, 0, vh_ldsc }; static TMLX vh_parm[VH_MUXES * VH_LINES] = { 0 }; - /* Forward references */ +/* Forward references */ static t_stat vh_rd (int32 *data, int32 PA, int32 access); static t_stat vh_wr (int32 data, int32 PA, int32 access); static t_stat vh_svc (UNIT *uptr); @@ -302,7 +301,7 @@ static t_stat vh_summ (FILE *st, UNIT *uptr, int32 val, void *desc); int32 tmxr_send_buffered_data (TMLN *lp); - /* SIMH I/O Structures */ +/* SIMH I/O Structures */ static DIB vh_dib = { IOBA_VH, @@ -386,7 +385,7 @@ DEVICE vh_dev = { DEV_FLTA | DEV_DISABLE | DEV_NET | DEV_QBUS | DEV_UBUS, /* flags */ }; - /* Interrupt routines */ +/* Interrupt routines */ static void vh_clr_rxint ( int32 vh ) { @@ -447,7 +446,7 @@ static int32 vh_txinta (void) } return (0); } - /* RX FIFO get/put routines */ +/* RX FIFO get/put routines */ /* return 0 on success, -1 on FIFO overflow */ @@ -574,7 +573,7 @@ static int32 fifo_get ( int32 vh ) } return (data & 0177777); } - /* TX Q manipulation */ +/* TX Q manipulation */ static int32 dq_tx_report ( int32 vh ) { @@ -603,7 +602,7 @@ static void q_tx_report ( int32 vh, vh_txq[vh][txq_idx[vh]] = CSR_TX_ACTION | data; txq_idx[vh] += 1; } - /* Channel get/put routines */ +/* Channel get/put routines */ static void HangupModem ( int32 vh, TMLX *lp, @@ -692,7 +691,7 @@ static void vh_getc ( int32 vh ) } } - /* I/O dispatch routines */ +/* I/O dispatch routines */ static t_stat vh_rd ( int32 *data, int32 PA, @@ -775,7 +774,7 @@ fprintf (stderr, "\rtqln %d\n", 64 - tmxr_tqln (lp->tmln)); } return (SCPE_OK); } - + static t_stat vh_wr ( int32 data, int32 PA, int32 access ) @@ -1039,7 +1038,7 @@ static t_stat vh_wr ( int32 data, } return (SCPE_OK); } - + static void doDMA ( int32 vh, int32 chan ) { @@ -1133,7 +1132,7 @@ static t_stat vh_svc ( UNIT *uptr ) return (SCPE_OK); } - /* init a channel on a controller */ +/* init a channel on a controller */ /* set for: send/receive 9600 @@ -1250,10 +1249,10 @@ static t_stat vh_reset ( DEVICE *dptr ) CLR_INT (VHTX); for (i = 0; i < VH_MUXES; i++) sim_cancel (&vh_unit[i]); - return (auto_config (RANK_VH, (dptr->flags & DEV_DIS) ? 0 : VH_MUXES)); + return (auto_config (dptr->name, (dptr->flags & DEV_DIS) ? 0 : VH_MUXES)); } - + static t_stat vh_attach ( UNIT *uptr, char *cptr ) { @@ -1298,7 +1297,7 @@ static t_stat vh_show_vec ( FILE *st, int32 val, void *desc ) { - return (show_vec (st, uptr, val, desc)); + return (show_vec (st, uptr, ((vh_desc.lines * 2) / VH_LINES), desc)); } static void debug_line ( FILE *st, diff --git a/PDP11/pdp11_xq.c b/PDP11/pdp11_xq.c index 93b9263c..439f1dbe 100644 --- a/PDP11/pdp11_xq.c +++ b/PDP11/pdp11_xq.c @@ -1,7 +1,7 @@ /* pdp11_xq.c: DEQNA/DELQA ethernet controller simulator ------------------------------------------------------------------------------ - Copyright (c) 2002-2004, David T. Hittner + Copyright (c) 2002-2005, 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"), @@ -66,6 +66,9 @@ Modification history: + 07-Sep-05 DTH Removed unused variable + 16-Aug-05 RMS Fixed C++ declaration and cast problems + 01-Dec-04 DTH Added runtime attach prompt 27-Feb-04 DTH Removed struct timeb deuggers 31-Jan-04 DTH Replaced #ifdef debuggers with inline debugging 19-Jan-04 DTH Combined service timers into one for efficiency @@ -206,6 +209,7 @@ extern int32 tmr_poll, clk_tps; extern FILE* sim_deb; +extern char* read_line (char *ptr, int32 size, FILE *stream); /* forward declarations */ t_stat xq_rd(int32* data, int32 PA, int32 access); @@ -1869,14 +1873,25 @@ t_stat xq_attach(UNIT* uptr, char* cptr) t_stat status; char* tptr; CTLR* xq = xq_unit2ctlr(uptr); + char buffer[80]; /* buffer for runtime input */ sim_debug(DBG_TRC, xq->dev, "xq_attach(cptr=%s)\n", cptr); - tptr = malloc(strlen(cptr) + 1); + /* runtime selection of ethernet port? */ + if (*cptr == '?') { /* I/O style derived from main() */ + memset (buffer, 0, sizeof(buffer)); /* clear read buffer */ + eth_show (stdout, uptr, 0, NULL); /* show ETH devices */ + printf ("Select device (ethX or )? "); /* prompt for device */ + cptr = read_line (buffer, sizeof(buffer), stdin); /* read command line */ + if (cptr == NULL) return SCPE_ARG; /* ignore EOF */ + if (*cptr == 0) return SCPE_ARG; /* ignore blank */ + } /* resume attaching */ + + tptr = (char *) malloc(strlen(cptr) + 1); if (tptr == NULL) return SCPE_MEM; strcpy(tptr, cptr); - xq->var->etherface = malloc(sizeof(ETH_DEV)); + xq->var->etherface = (ETH_DEV *) malloc(sizeof(ETH_DEV)); if (!xq->var->etherface) return SCPE_MEM; status = eth_open(xq->var->etherface, cptr, xq->dev, DBG_ETH); @@ -1906,7 +1921,7 @@ t_stat xq_detach(UNIT* uptr) sim_debug(DBG_TRC, xq->dev, "xq_detach()\n"); if (uptr->flags & UNIT_ATT) { - t_stat status = eth_close (xq->var->etherface); + eth_close (xq->var->etherface); free(xq->var->etherface); xq->var->etherface = 0; free(uptr->filename); diff --git a/PDP11/pdp11_xq.h b/PDP11/pdp11_xq.h index b54339c6..c90edff5 100644 --- a/PDP11/pdp11_xq.h +++ b/PDP11/pdp11_xq.h @@ -1,7 +1,7 @@ /* pdp11_xq.h: DEQNA/DELQA ethernet controller information ------------------------------------------------------------------------------ - Copyright (c) 2002-2004, David T. Hittner + Copyright (c) 2002-2005, 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"), @@ -28,6 +28,7 @@ Modification history: + 07-Jul-05 RMS Removed extraneous externs 20-Jan-04 DTH Added new sanity timer and system id timer 19-Jan-04 DTH Added XQ_SERVICE_INTERVAL, poll 09-Jan-04 DTH Added Boot PDP diagnostic definition, XI/RI combination @@ -56,67 +57,65 @@ #ifndef _PDP11_XQ_H #define _PDP11_XQ_H -#if defined (VM_PDP10) /* PDP10 version */ +#if defined (VM_PDP10) /* PDP10 version */ #error "DEQNA/DELQA not supported on PDP10!" -#elif defined (VM_VAX) /* VAX version */ +#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 */ +#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 */ +#else /* PDP-11 version */ #include "pdp11_defs.h" -#define XQ_RDX 8 -#define XQ_WID 16 +#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" -#define XQ_QUE_MAX 500 /* read queue size in packets */ -#define XQ_FILTER_MAX 14 /* number of filters allowed */ -#define XQ_SERVICE_INTERVAL 100 /* polling interval - X per second */ -#define XQ_SYSTEM_ID_SECS 540 /* seconds before system ID timer expires */ -#define XQ_HW_SANITY_SECS 240 /* seconds before HW sanity timer expires */ -#define XQ_MAX_CONTROLLERS 2 /* maximum controllers allowed */ +#define XQ_QUE_MAX 500 /* read queue size in packets */ +#define XQ_FILTER_MAX 14 /* number of filters allowed */ +#define XQ_SERVICE_INTERVAL 100 /* polling interval - X per second */ +#define XQ_SYSTEM_ID_SECS 540 /* seconds before system ID timer expires */ +#define XQ_HW_SANITY_SECS 240 /* seconds before HW sanity timer expires */ +#define XQ_MAX_CONTROLLERS 2 /* maximum controllers allowed */ enum xq_type {XQ_T_DEQNA, XQ_T_DELQA}; struct xq_sanity { - int enabled; /* sanity timer enabled? 2=HW, 1=SW, 0=off */ - int quarter_secs; /* sanity timer value in 1/4 seconds */ - int max; /* maximum timeout (based on poll) */ - int timer; /* countdown timer */ + int enabled; /* sanity timer enabled? 2=HW, 1=SW, 0=off */ + int quarter_secs; /* sanity timer value in 1/4 seconds */ + int max; /* maximum timeout (based on poll) */ + int timer; /* countdown timer */ }; 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 */ + 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 */ + 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 */ +struct xq_meb { /* MEB block */ uint8 type; uint8 add_lo; uint8 add_mi; @@ -126,24 +125,24 @@ struct xq_meb { /* MEB block */ }; 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 */ - int poll; /* poll ethernet times/sec */ - struct xq_sanity sanity; /* sanity timer information */ - /*- initialized values - DO NOT MOVE */ + /*+ 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 */ + int poll; /* poll ethernet times/sec */ + struct xq_sanity sanity; /* sanity timer information */ + /*- initialized values - DO NOT MOVE */ - /* I/O register storage */ + /* I/O register storage */ uint16 addr[6]; uint16 rbdl[2]; uint16 xbdl[2]; uint16 var; uint16 csr; - uint32 irq; /* interrupt request flag */ + uint32 irq; /* interrupt request flag */ - /* buffers, etc. */ + /* buffers, etc. */ struct xq_setup setup; struct xq_stats stats; uint8 mac_checksum[2]; @@ -156,79 +155,79 @@ struct xq_device { ETH_PACK read_buffer; ETH_PACK write_buffer; ETH_QUE ReadQ; - int idtmr; /* countdown for ID Timer */ + int idtmr; /* countdown for ID Timer */ }; struct xq_controller { - DEVICE* dev; /* device block */ - UNIT* unit; /* unit block */ - DIB* dib; /* device interface block */ - struct xq_device* var; /* controller-specific variables */ + 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] */ +#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_CSR_BP 0x0208 /* Boot PDP diagnostic ROM */ -#define XQ_CSR_XIRI 0X8080 /* Transmit & Receive Interrupts */ +#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_CSR_BP 0x0208 /* Boot PDP diagnostic ROM */ +#define XQ_CSR_XIRI 0X8080 /* Transmit & Receive Interrupts */ -#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] */ +#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_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_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 */ +#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 */ /* debugging bitmaps */ -#define DBG_TRC 0x0001 /* trace routine calls */ -#define DBG_REG 0x0002 /* trace read/write registers */ -#define DBG_CSR 0x0004 /* watch CSR */ -#define DBG_VAR 0x0008 /* watch VAR */ -#define DBG_WRN 0x0010 /* display warnings */ -#define DBG_SAN 0x0020 /* display sanity timer info */ -#define DBG_SET 0x0040 /* display setup info */ -#define DBG_PCK 0x0080 /* display packets */ -#define DBG_ETH 0x8000 /* debug ethernet device */ +#define DBG_TRC 0x0001 /* trace routine calls */ +#define DBG_REG 0x0002 /* trace read/write registers */ +#define DBG_CSR 0x0004 /* watch CSR */ +#define DBG_VAR 0x0008 /* watch VAR */ +#define DBG_WRN 0x0010 /* display warnings */ +#define DBG_SAN 0x0020 /* display sanity timer info */ +#define DBG_SET 0x0040 /* display setup info */ +#define DBG_PCK 0x0080 /* display packets */ +#define DBG_ETH 0x8000 /* debug ethernet device */ -#endif /* _PDP11_XQ_H */ +#endif /* _PDP11_XQ_H */ diff --git a/PDP11/pdp11_xq_bootrom.h b/PDP11/pdp11_xq_bootrom.h index 9a0b954c..e12d3519 100644 --- a/PDP11/pdp11_xq_bootrom.h +++ b/PDP11/pdp11_xq_bootrom.h @@ -1,7 +1,7 @@ /* pdp11_xq_bootrom.h: DEQNA/DELQA bootrom data ------------------------------------------------------------------------------ - Copyright (c) 2003, David T. Hittner + Copyright (c) 2003-2005, 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"), @@ -307,6 +307,6 @@ 0000000,0000000,0000000,0000000,0000000,0000000,0000000,0000000, 0000000,0000000,0000000,0000000,0000000,0000000,0000000,0102206 }; -#endif /* VM_PDP11 */ +#endif /* VM_PDP11 */ -#endif /* _PDP11_XQ_BOOTROM_H */ +#endif /* _PDP11_XQ_BOOTROM_H */ diff --git a/PDP11/pdp11_xu.c b/PDP11/pdp11_xu.c index 8ef4c4a7..ab53514a 100644 --- a/PDP11/pdp11_xu.c +++ b/PDP11/pdp11_xu.c @@ -52,6 +52,9 @@ Modification history: + 07-Sep-05 DTH Corrected runt packet processing (found by Tim Chapman), + Removed unused variable + 16-Aug-05 RMS Fixed C++ declaration and cast problems 10-Mar-05 RMS Fixed equality test in RCSTAT (from Mark Hittinger) 16-Jan-04 DTH Added more info to SHOW MOD commands 09-Jan-04 DTH Made XU floating address so that XUB will float correctly @@ -971,7 +974,6 @@ void xu_process_transmit(CTLR* xu) uint32 segb, ba; int slen, wlen, i, off, giant, runt; t_stat rstatus, wstatus; - const ETH_MAC zeros = {0, 0, 0, 0, 0, 0}; sim_debug(DBG_TRC, xu->dev, "xu_process_transmit()\n"); @@ -1023,9 +1025,10 @@ void xu_process_transmit(CTLR* xu) if (xu->var->txhdr[2] & TXR_ENF) { /* make sure packet is minimum length */ - if ((xu->var->write_buffer.len < ETH_MIN_PACKET) && (xu->var->mode & MODE_TPAD)) { - xu->var->write_buffer.len = ETH_MIN_PACKET; - runt = 1; + if (xu->var->write_buffer.len < ETH_MIN_PACKET) { + xu->var->write_buffer.len = ETH_MIN_PACKET; /* pad packet to minimum length */ + if ((xu->var->mode & MODE_TPAD) == 0) /* if pad mode is NOT on, set runt error flag */ + runt = 1; } /* are we in internal loopback mode ? */ @@ -1297,11 +1300,11 @@ t_stat xu_attach(UNIT* uptr, char* cptr) CTLR* xu = xu_unit2ctlr(uptr); sim_debug(DBG_TRC, xu->dev, "xu_attach(cptr=%s)\n", cptr); - tptr = malloc(strlen(cptr) + 1); + tptr = (char *) malloc(strlen(cptr) + 1); if (tptr == NULL) return SCPE_MEM; strcpy(tptr, cptr); - xu->var->etherface = malloc(sizeof(ETH_DEV)); + xu->var->etherface = (ETH_DEV *) malloc(sizeof(ETH_DEV)); if (!xu->var->etherface) return SCPE_MEM; status = eth_open(xu->var->etherface, cptr, xu->dev, DBG_ETH); diff --git a/PDP11/pdp11_xu.h b/PDP11/pdp11_xu.h index 616201ce..973b07e6 100644 --- a/PDP11/pdp11_xu.h +++ b/PDP11/pdp11_xu.h @@ -1,7 +1,7 @@ /* pdp11_xu.h: DEUNA/DELUA ethernet controller information ------------------------------------------------------------------------------ - Copyright (c) 2003-2004, David T. Hittner + Copyright (c) 2003-2005, 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"), @@ -28,6 +28,7 @@ Modification history: + 07-Jul-05 RMS Removed extraneous externs 05-Jan-04 DTH Added network statistics 31-Dec-03 DTH Added reserved states 28-Dec-03 DTH Corrected MODE bitmasks @@ -42,43 +43,40 @@ #define _PDP11_XU_H -#if defined (VM_PDP10) /* PDP10 version */ +#if defined (VM_PDP10) /* PDP10 version */ #include "pdp10_defs.h" -#define XU_RDX 8 -#define XU_WID 16 +#define XU_RDX 8 +#define XU_WID 16 extern int32 int_req; -extern int32 int_vec[32]; -#elif defined (VM_VAX) /* VAX version */ +#elif defined (VM_VAX) /* VAX version */ #include "vax_defs.h" -#define XU_RDX 8 -#define XU_WID 16 +#define XU_RDX 8 +#define XU_WID 16 extern int32 int_req[IPL_HLVL]; -extern int32 int_vec[IPL_HLVL][32]; -#else /* PDP-11 version */ +#else /* PDP-11 version */ #include "pdp11_defs.h" -#define XU_RDX 8 -#define XU_WID 16 +#define XU_RDX 8 +#define XU_WID 16 extern int32 int_req[IPL_HLVL]; -extern int32 int_vec[IPL_HLVL][32]; -#endif /* VM_PDP10 */ +#endif /* VM_PDP10 */ #include "sim_ether.h" -#define XU_QUE_MAX 500 /* message queue array */ -#define XU_FILTER_MAX 11 /* mac + 10 multicast addrs */ -#define XU_SERVICE_INTERVAL 100 /* times per second */ -#define XU_ID_TIMER_VAL 540 /* 9 min * 60 sec */ -#define UDBSIZE 100 /* max size of UDB (in words) */ +#define XU_QUE_MAX 500 /* message queue array */ +#define XU_FILTER_MAX 11 /* mac + 10 multicast addrs */ +#define XU_SERVICE_INTERVAL 100 /* times per second */ +#define XU_ID_TIMER_VAL 540 /* 9 min * 60 sec */ +#define UDBSIZE 100 /* max size of UDB (in words) */ enum xu_type {XU_T_DEUNA, XU_T_DELUA}; struct xu_setup { - int promiscuous; /* promiscuous mode enabled */ - int multicast; /* enable all multicast addresses */ - int mac_count; /* number of multicast mac addresses */ - ETH_MAC macs[XU_FILTER_MAX]; /* MAC addresses to respond to */ + int promiscuous; /* promiscuous mode enabled */ + int multicast; /* enable all multicast addresses */ + int mac_count; /* number of multicast mac addresses */ + ETH_MAC macs[XU_FILTER_MAX]; /* MAC addresses to respond to */ }; /* Network Statistics - @@ -87,219 +85,219 @@ struct xu_setup { things like incoming runts, collision tests, babbling, etc. */ struct xu_stats { - uint16 secs; /* seconds since last clear */ - uint32 frecv; /* frames received */ - uint32 mfrecv; /* multicast frames received */ - uint16 rxerf; /* receive error flags */ - uint32 frecve; /* frames received with errors */ - uint32 rbytes; /* data bytes received */ - uint32 mrbytes; /* multicast data bytes received */ - uint16 rlossi; /* received frames lost - internal err */ - uint16 rlossl; /* received frames lost - local buffers */ - uint32 ftrans; /* frames transmitted */ - uint32 mftrans; /* multicast frames transmitted */ - uint32 ftrans3; /* frames transmitted with 3+ tries */ - uint32 ftrans2; /* frames transmitted - two tries */ - uint32 ftransd; /* frames transmitted - deferred */ - uint32 tbytes; /* data bytes transmitted */ - uint32 mtbytes; /* multicast data bytes transmitted */ - uint16 txerf; /* transmit error flags summary */ - uint16 ftransa; /* transmit frames aborted */ - uint16 txccf; /* transmit collision test failure */ - uint16 porterr; /* port driver errors */ - uint16 bablcnt; /* babble counter */ + uint16 secs; /* seconds since last clear */ + uint32 frecv; /* frames received */ + uint32 mfrecv; /* multicast frames received */ + uint16 rxerf; /* receive error flags */ + uint32 frecve; /* frames received with errors */ + uint32 rbytes; /* data bytes received */ + uint32 mrbytes; /* multicast data bytes received */ + uint16 rlossi; /* received frames lost - internal err */ + uint16 rlossl; /* received frames lost - local buffers */ + uint32 ftrans; /* frames transmitted */ + uint32 mftrans; /* multicast frames transmitted */ + uint32 ftrans3; /* frames transmitted with 3+ tries */ + uint32 ftrans2; /* frames transmitted - two tries */ + uint32 ftransd; /* frames transmitted - deferred */ + uint32 tbytes; /* data bytes transmitted */ + uint32 mtbytes; /* multicast data bytes transmitted */ + uint16 txerf; /* transmit error flags summary */ + uint16 ftransa; /* transmit frames aborted */ + uint16 txccf; /* transmit collision test failure */ + uint16 porterr; /* port driver errors */ + uint16 bablcnt; /* babble counter */ }; struct xu_device { - /*+ initialized values - DO NOT MOVE */ - ETH_PCALLBACK rcallback; /* read callback routine */ - ETH_PCALLBACK wcallback; /* write callback routine */ - ETH_MAC mac; /* MAC address */ - enum xu_type type; /* controller type */ - /*- initialized values - DO NOT MOVE */ + /*+ initialized values - DO NOT MOVE */ + ETH_PCALLBACK rcallback; /* read callback routine */ + ETH_PCALLBACK wcallback; /* write callback routine */ + ETH_MAC mac; /* MAC address */ + enum xu_type type; /* controller type */ + /*- initialized values - DO NOT MOVE */ - /* I/O register storage */ - uint32 irq; /* interrupt request flag */ + /* I/O register storage */ + uint32 irq; /* interrupt request flag */ - /* buffers, etc. */ + /* buffers, etc. */ ETH_DEV* etherface; ETH_PACK read_buffer; ETH_PACK write_buffer; ETH_QUE ReadQ; - int idtmr; /* countdown for ID Timer */ - int sectmr; /* countup for one second timer */ + int idtmr; /* countdown for ID Timer */ + int sectmr; /* countup for one second timer */ struct xu_setup setup; - struct xu_stats stats; /* reportable network statistics */ + struct xu_stats stats; /* reportable network statistics */ - /* copied from dec_deuna.h */ - uint16 pcsr0; /* primary DEUNA registers */ + /* copied from dec_deuna.h */ + uint16 pcsr0; /* primary DEUNA registers */ uint16 pcsr1; uint16 pcsr2; uint16 pcsr3; - uint32 mode; /* mode register */ - uint32 pcbb; /* port command block base */ - uint32 stat; /* extended port status */ + uint32 mode; /* mode register */ + uint32 pcbb; /* port command block base */ + uint32 stat; /* extended port status */ - uint32 tdrb; /* transmit desc ring base */ - uint32 telen; /* transmit desc ring entry len */ - uint32 trlen; /* transmit desc ring length */ - uint32 txnext; /* transmit buffer pointer */ - uint32 rdrb; /* receive desc ring base */ - uint32 relen; /* receive desc ring entry len */ - uint32 rrlen; /* receive desc ring length */ - uint32 rxnext; /* receive buffer pointer */ + uint32 tdrb; /* transmit desc ring base */ + uint32 telen; /* transmit desc ring entry len */ + uint32 trlen; /* transmit desc ring length */ + uint32 txnext; /* transmit buffer pointer */ + uint32 rdrb; /* receive desc ring base */ + uint32 relen; /* receive desc ring entry len */ + uint32 rrlen; /* receive desc ring length */ + uint32 rxnext; /* receive buffer pointer */ - uint16 pcb[4]; /* copy of Port Command Block */ - uint16 udb[UDBSIZE]; /* copy of Unibus Data Block */ - uint16 rxhdr[4]; /* content of RX ring entry, during wait */ - uint16 txhdr[4]; /* content of TX ring entry, during xmit */ + uint16 pcb[4]; /* copy of Port Command Block */ + uint16 udb[UDBSIZE]; /* copy of Unibus Data Block */ + uint16 rxhdr[4]; /* content of RX ring entry, during wait */ + uint16 txhdr[4]; /* content of TX ring entry, during xmit */ }; struct xu_controller { - DEVICE* dev; /* device block */ - UNIT* unit; /* unit block */ - DIB* dib; /* device interface block */ - struct xu_device* var; /* controller-specific variables */ + DEVICE* dev; /* device block */ + UNIT* unit; /* unit block */ + DIB* dib; /* device interface block */ + struct xu_device* var; /* controller-specific variables */ }; typedef struct xu_controller CTLR; /* PCSR0 register definitions */ -#define PCSR0_SERI 0100000 /* <15> Status Error Intr */ -#define PCSR0_PCEI 0040000 /* <14> Port Command Error Intr */ -#define PCSR0_RXI 0020000 /* <13> Receive Interrupt */ -#define PCSR0_TXI 0010000 /* <12> Transmit Interrupt */ -#define PCSR0_DNI 0004000 /* <11> Done Interrupt */ -#define PCSR0_RCBI 0002000 /* <10> Recv Buffer Unavail Intr */ -#define PCSR0_USCI 0000400 /* <08> Unsolicited State Chg Inter */ -#define PCSR0_INTR 0000200 /* <07> Interrupt Summary */ -#define PCSR0_INTE 0000100 /* <06> Interrupt Enable */ -#define PCSR0_RSET 0000040 /* <05> Reset */ -#define PCSR0_PCMD 0000017 /* <03:00> Port Command field */ +#define PCSR0_SERI 0100000 /* <15> Status Error Intr */ +#define PCSR0_PCEI 0040000 /* <14> Port Command Error Intr */ +#define PCSR0_RXI 0020000 /* <13> Receive Interrupt */ +#define PCSR0_TXI 0010000 /* <12> Transmit Interrupt */ +#define PCSR0_DNI 0004000 /* <11> Done Interrupt */ +#define PCSR0_RCBI 0002000 /* <10> Recv Buffer Unavail Intr */ +#define PCSR0_USCI 0000400 /* <08> Unsolicited State Chg Inter */ +#define PCSR0_INTR 0000200 /* <07> Interrupt Summary */ +#define PCSR0_INTE 0000100 /* <06> Interrupt Enable */ +#define PCSR0_RSET 0000040 /* <05> Reset */ +#define PCSR0_PCMD 0000017 /* <03:00> Port Command field */ /* PCSR0 Port Commands */ -#define CMD_NOOP 000 /* No-op */ -#define CMD_GETPCBB 001 /* Get PCB base */ -#define CMD_GETCMD 002 /* Get Command */ -#define CMD_SELFTEST 003 /* Self-test init */ -#define CMD_START 004 /* Start xmit/recv */ -#define CMD_BOOT 005 /* Boot */ -#define CMD_RSV06 006 /* Reserved */ -#define CMD_RSV07 007 /* Reserved */ -#define CMD_PDMD 010 /* Polling Demand */ -#define CMD_RSV11 011 /* Reserved */ -#define CMD_RSV12 012 /* Reserved */ -#define CMD_RSV13 013 /* Reserved */ -#define CMD_RSV14 014 /* Reserved */ -#define CMD_RSV15 015 /* Reserved */ -#define CMD_HALT 016 /* Halt */ -#define CMD_STOP 017 /* Stop */ +#define CMD_NOOP 000 /* No-op */ +#define CMD_GETPCBB 001 /* Get PCB base */ +#define CMD_GETCMD 002 /* Get Command */ +#define CMD_SELFTEST 003 /* Self-test init */ +#define CMD_START 004 /* Start xmit/recv */ +#define CMD_BOOT 005 /* Boot */ +#define CMD_RSV06 006 /* Reserved */ +#define CMD_RSV07 007 /* Reserved */ +#define CMD_PDMD 010 /* Polling Demand */ +#define CMD_RSV11 011 /* Reserved */ +#define CMD_RSV12 012 /* Reserved */ +#define CMD_RSV13 013 /* Reserved */ +#define CMD_RSV14 014 /* Reserved */ +#define CMD_RSV15 015 /* Reserved */ +#define CMD_HALT 016 /* Halt */ +#define CMD_STOP 017 /* Stop */ /* PCSR1 register definitions */ -#define PCSR1_XPWR 0100000 /* <15> Tranceiver power failure */ -#define PCSR1_ICAB 0040000 /* <14> Port/Link cable failure */ -#define PCSR1_ECOD 0037400 /* <13:08> Self-test error code */ -#define PCSR1_PCTO 0000200 /* <07> Port Command Timeout */ -#define PCSR1_TYPE 0000160 /* <06:04> Interface type */ -#define PCSR1_STATE 0000017 /* <03:00> State: */ +#define PCSR1_XPWR 0100000 /* <15> Tranceiver power failure */ +#define PCSR1_ICAB 0040000 /* <14> Port/Link cable failure */ +#define PCSR1_ECOD 0037400 /* <13:08> Self-test error code */ +#define PCSR1_PCTO 0000200 /* <07> Port Command Timeout */ +#define PCSR1_TYPE 0000160 /* <06:04> Interface type */ +#define PCSR1_STATE 0000017 /* <03:00> State: */ /* PCSR1 Types */ -#define TYPE_DEUNA (0 << 4) /* Controller is a DEUNA */ -#define TYPE_DELUA (1 << 4) /* Controller is a DELUA */ +#define TYPE_DEUNA (0 << 4) /* Controller is a DEUNA */ +#define TYPE_DELUA (1 << 4) /* Controller is a DELUA */ /* PCSR1 States */ -#define STATE_RESET 000 /* Reset */ -#define STATE_PLOAD 001 /* Primary Load */ -#define STATE_READY 002 /* Ready */ -#define STATE_RUNNING 003 /* Running */ -#define STATE_UHALT 005 /* UNIBUS Halted */ -#define STATE_NHALT 006 /* NI Halted */ -#define STATE_NUHALT 007 /* NI and UNIBUS Halted */ -#define STATE_HALT 010 /* Halted */ -#define STATE_SLOAD 017 /* Secondary Load */ +#define STATE_RESET 000 /* Reset */ +#define STATE_PLOAD 001 /* Primary Load */ +#define STATE_READY 002 /* Ready */ +#define STATE_RUNNING 003 /* Running */ +#define STATE_UHALT 005 /* UNIBUS Halted */ +#define STATE_NHALT 006 /* NI Halted */ +#define STATE_NUHALT 007 /* NI and UNIBUS Halted */ +#define STATE_HALT 010 /* Halted */ +#define STATE_SLOAD 017 /* Secondary Load */ /* Status register definitions */ -#define STAT_ERRS 0100000 /* <15> error summary */ -#define STAT_MERR 0040000 /* <14> multiple errors */ -#define STAT_BABL 0020000 /* <13> Transmitter on too long [DELUA only] */ -#define STAT_CERR 0010000 /* <12> collision test error */ -#define STAT_TMOT 0004000 /* <11> UNIBUS timeout */ -#define STAT_RRNG 0001000 /* <09> receive ring error */ -#define STAT_TRNG 0000400 /* <08> transmit ring error */ -#define STAT_PTCH 0000200 /* <07> ROM patch */ -#define STAT_RRAM 0000100 /* <06> running from RAM */ -#define STAT_RREV 0000077 /* <05:00> ROM version */ +#define STAT_ERRS 0100000 /* <15> error summary */ +#define STAT_MERR 0040000 /* <14> multiple errors */ +#define STAT_BABL 0020000 /* <13> Transmitter on too long [DELUA only] */ +#define STAT_CERR 0010000 /* <12> collision test error */ +#define STAT_TMOT 0004000 /* <11> UNIBUS timeout */ +#define STAT_RRNG 0001000 /* <09> receive ring error */ +#define STAT_TRNG 0000400 /* <08> transmit ring error */ +#define STAT_PTCH 0000200 /* <07> ROM patch */ +#define STAT_RRAM 0000100 /* <06> running from RAM */ +#define STAT_RREV 0000077 /* <05:00> ROM version */ /* Mode definitions */ -#define MODE_PROM 0100000 /* <15> Promiscuous Mode */ -#define MODE_ENAL 0040000 /* <14> Enable All Multicasts */ -#define MODE_DRDC 0020000 /* <13> Disable Data Chaining */ -#define MODE_TPAD 0010000 /* <12> Transmit Msg Pad Enable */ -#define MODE_ECT 0004000 /* <11> Enable Collision Test */ -#define MODE_DMNT 0001000 /* <09> Disable Maint Message */ -#define MODE_INTL 0000200 /* <07> Internal Loopback [DELUA only] */ -#define MODE_DTCR 0000010 /* <03> Disable Transmit CRC */ -#define MODE_LOOP 0000004 /* <02> Internal Loopback Mode */ -#define MODE_HDPX 0000001 /* <00> Half-Duplex Mode */ +#define MODE_PROM 0100000 /* <15> Promiscuous Mode */ +#define MODE_ENAL 0040000 /* <14> Enable All Multicasts */ +#define MODE_DRDC 0020000 /* <13> Disable Data Chaining */ +#define MODE_TPAD 0010000 /* <12> Transmit Msg Pad Enable */ +#define MODE_ECT 0004000 /* <11> Enable Collision Test */ +#define MODE_DMNT 0001000 /* <09> Disable Maint Message */ +#define MODE_INTL 0000200 /* <07> Internal Loopback [DELUA only] */ +#define MODE_DTCR 0000010 /* <03> Disable Transmit CRC */ +#define MODE_LOOP 0000004 /* <02> Internal Loopback Mode */ +#define MODE_HDPX 0000001 /* <00> Half-Duplex Mode */ /* Function Code definitions */ -#define FC_NOOP 0000000 /* no-op */ -#define FC_LSM 0000001 /* Load and Start Microaddress */ -#define FC_RDPA 0000002 /* Read Default Physical Address */ -#define FC_RPA 0000004 /* Read Physical Address */ -#define FC_WPA 0000005 /* Write Physical Address */ -#define FC_RMAL 0000006 /* Read Multicast Address List */ -#define FC_WMAL 0000007 /* Write Multicast Address List */ -#define FC_RRF 0000010 /* Read Ring Format */ -#define FC_WRF 0000011 /* Write Ring Format */ -#define FC_RDCTR 0000012 /* Read Counters */ -#define FC_RDCLCTR 0000013 /* Read and Clear Counters */ -#define FC_RMODE 0000014 /* Read Mode */ -#define FC_WMODE 0000015 /* Write Mode */ -#define FC_RSTAT 0000016 /* Read Status */ -#define FC_RCSTAT 0000017 /* Read and Clear Status */ -#define FC_DIM 0000020 /* Dump Internal Memory */ -#define FC_LIM 0000021 /* Load Internal Memory */ -#define FC_RSID 0000022 /* Read System ID parameters */ -#define FC_WSID 0000023 /* Write System ID parameters */ -#define FC_RLSA 0000024 /* Read Load Server Address */ -#define FC_WLSA 0000025 /* Write Load Server Address */ +#define FC_NOOP 0000000 /* no-op */ +#define FC_LSM 0000001 /* Load and Start Microaddress */ +#define FC_RDPA 0000002 /* Read Default Physical Address */ +#define FC_RPA 0000004 /* Read Physical Address */ +#define FC_WPA 0000005 /* Write Physical Address */ +#define FC_RMAL 0000006 /* Read Multicast Address List */ +#define FC_WMAL 0000007 /* Write Multicast Address List */ +#define FC_RRF 0000010 /* Read Ring Format */ +#define FC_WRF 0000011 /* Write Ring Format */ +#define FC_RDCTR 0000012 /* Read Counters */ +#define FC_RDCLCTR 0000013 /* Read and Clear Counters */ +#define FC_RMODE 0000014 /* Read Mode */ +#define FC_WMODE 0000015 /* Write Mode */ +#define FC_RSTAT 0000016 /* Read Status */ +#define FC_RCSTAT 0000017 /* Read and Clear Status */ +#define FC_DIM 0000020 /* Dump Internal Memory */ +#define FC_LIM 0000021 /* Load Internal Memory */ +#define FC_RSID 0000022 /* Read System ID parameters */ +#define FC_WSID 0000023 /* Write System ID parameters */ +#define FC_RLSA 0000024 /* Read Load Server Address */ +#define FC_WLSA 0000025 /* Write Load Server Address */ /* Transmitter Ring definitions */ -#define TXR_OWN 0100000 /* <15> we own it (1) */ -#define TXR_ERRS 0040000 /* <14> error summary */ -#define TXR_MTCH 0020000 /* <13> Station Match */ -#define TXR_MORE 0010000 /* <12> Mult Retries Needed */ -#define TXR_ONE 0004000 /* <11> One Collision */ -#define TXR_DEF 0002000 /* <10> Deferred */ -#define TXR_STF 0001000 /* <09> Start Of Frame */ -#define TXR_ENF 0000400 /* <08> End Of Frame */ -#define TXR_BUFL 0100000 /* <15> Buffer Length Error */ -#define TXR_UBTO 0040000 /* <14> UNIBUS TimeOut */ -#define TXR_UFLO 0020000 /* <13> Underflow Error */ -#define TXR_LCOL 0010000 /* <12> Late Collision */ -#define TXR_LCAR 0004000 /* <11> Lost Carrier */ -#define TXR_RTRY 0002000 /* <10> Retry Failure (16x) */ -#define TXR_TDR 0001777 /* <9:0> TDR value if RTRY=1 */ +#define TXR_OWN 0100000 /* <15> we own it (1) */ +#define TXR_ERRS 0040000 /* <14> error summary */ +#define TXR_MTCH 0020000 /* <13> Station Match */ +#define TXR_MORE 0010000 /* <12> Mult Retries Needed */ +#define TXR_ONE 0004000 /* <11> One Collision */ +#define TXR_DEF 0002000 /* <10> Deferred */ +#define TXR_STF 0001000 /* <09> Start Of Frame */ +#define TXR_ENF 0000400 /* <08> End Of Frame */ +#define TXR_BUFL 0100000 /* <15> Buffer Length Error */ +#define TXR_UBTO 0040000 /* <14> UNIBUS TimeOut */ +#define TXR_UFLO 0020000 /* <13> Underflow Error */ +#define TXR_LCOL 0010000 /* <12> Late Collision */ +#define TXR_LCAR 0004000 /* <11> Lost Carrier */ +#define TXR_RTRY 0002000 /* <10> Retry Failure (16x) */ +#define TXR_TDR 0001777 /* <9:0> TDR value if RTRY=1 */ /* Receiver Ring definitions */ -#define RXR_OWN 0100000 /* <15> we own it (1) */ -#define RXR_ERRS 0040000 /* <14> Error Summary */ -#define RXR_FRAM 0020000 /* <13> Frame Error */ -#define RXR_OFLO 0010000 /* <12> Message Overflow */ -#define RXR_CRC 0004000 /* <11> CRC Check Error */ -#define RXR_STF 0001000 /* <09> Start Of Frame */ -#define RXR_ENF 0000400 /* <08> End Of Frame */ -#define RXR_BUFL 0100000 /* <15> Buffer Length error */ -#define RXR_UBTO 0040000 /* <14> UNIBUS TimeOut */ -#define RXR_NCHN 0020000 /* <13> No Data Chaining */ -#define RXR_OVRN 0010000 /* <12> Overrun Error [DELUA only] */ -#define RXR_MLEN 0007777 /* <11:0> Message Length */ +#define RXR_OWN 0100000 /* <15> we own it (1) */ +#define RXR_ERRS 0040000 /* <14> Error Summary */ +#define RXR_FRAM 0020000 /* <13> Frame Error */ +#define RXR_OFLO 0010000 /* <12> Message Overflow */ +#define RXR_CRC 0004000 /* <11> CRC Check Error */ +#define RXR_STF 0001000 /* <09> Start Of Frame */ +#define RXR_ENF 0000400 /* <08> End Of Frame */ +#define RXR_BUFL 0100000 /* <15> Buffer Length error */ +#define RXR_UBTO 0040000 /* <14> UNIBUS TimeOut */ +#define RXR_NCHN 0020000 /* <13> No Data Chaining */ +#define RXR_OVRN 0010000 /* <12> Overrun Error [DELUA only] */ +#define RXR_MLEN 0007777 /* <11:0> Message Length */ /* debugging bitmaps */ -#define DBG_TRC 0x0001 /* trace routine calls */ -#define DBG_REG 0x0002 /* trace read/write registers */ -#define DBG_WRN 0x0004 /* display warnings */ -#define DBG_ETH 0x8000 /* debug ethernet device */ +#define DBG_TRC 0x0001 /* trace routine calls */ +#define DBG_REG 0x0002 /* trace read/write registers */ +#define DBG_WRN 0x0004 /* display warnings */ +#define DBG_ETH 0x8000 /* debug ethernet device */ -#endif /* _PDP11_XU_H */ +#endif /* _PDP11_XU_H */ diff --git a/PDP18B/pdp18b_cpu.c b/PDP18B/pdp18b_cpu.c index cb6fdfd8..8fd5adbb 100644 --- a/PDP18B/pdp18b_cpu.c +++ b/PDP18B/pdp18b_cpu.c @@ -1,6 +1,6 @@ /* pdp18b_cpu.c: 18b PDP CPU simulator - Copyright (c) 1993-2004, Robert M Supnik + Copyright (c) 1993-2005, 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"), @@ -19,50 +19,52 @@ 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 + 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 + cpu PDP-4/7/9/15 central processor - 06-Nov-04 RMS Added =n to SHOW HISTORY - 26-Mar-04 RMS Fixed warning from -std=c99 - 14-Jan-04 RMS Fixed g_mode in XVM implementation - PDP-15 index, autoincrement generate 18b addresses - Revised IO device call interface - 31-Dec-03 RMS Fixed bug in cpu_set_hist - 02-Nov-03 RMS Changed PDP-9,-15 default to API - 26-Oct-03 RMS Fixed bug in PDP-4,-7,-9 autoincrement addressing - 19-Sep-03 RMS Changed instruction history to be dynamically sized - 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 + 16-Aug-05 RMS Fixed C++ declaration and cast problems + 22-Jul-05 RMS Removed AAS, error in V1 reference manual + 06-Nov-04 RMS Added =n to SHOW HISTORY + 26-Mar-04 RMS Fixed warning from -std=c99 + 14-Jan-04 RMS Fixed g_mode in XVM implementation + PDP-15 index, autoincrement generate 18b addresses + Revised IO device call interface + 31-Dec-03 RMS Fixed bug in cpu_set_hist + 02-Nov-03 RMS Changed PDP-9,-15 default to API + 26-Oct-03 RMS Fixed bug in PDP-4,-7,-9 autoincrement addressing + 19-Sep-03 RMS Changed instruction history to be dynamically sized + 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 @@ -72,23 +74,22 @@ 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 + 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 @@ -106,21 +107,21 @@ | op |in| X| address | memory reference +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - <0:3> mnemonic action + <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 + 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 @@ -142,28 +143,27 @@ 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: + + 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) + | | | | | | | | | | | | | | + | | | | | | | | | | | | | +- 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: @@ -189,9 +189,8 @@ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ Indirection is always single level. -*/ - -/* On the PDP-15, the index operate format is: + + 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 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ @@ -207,20 +206,20 @@ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | 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) + | | | | | | | | | | | | | + | | | | | | | | | | | | +- 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. @@ -232,12 +231,11 @@ | 1 1 1 1 1| immediate | LAW +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - <0:4> mnemonic action + <0:4> mnemonic action - 76 LAW AC = IR -*/ - -/* This routine is the instruction decode routine for the 18b PDP's. + 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. @@ -246,11 +244,11 @@ 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 + 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] @@ -265,112 +263,114 @@ 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 + 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 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 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_API 0x40000000 -#define HIST_PI 0x20000000 -#define HIST_PC 0x10000000 -#define HIST_MIN 64 -#define HIST_MAX 65536 -#define HIST_M_LVL 0x3F -#define HIST_V_LVL 6 -struct InstHistory { - int32 pc; - int32 ir; - int32 ir1; - int32 lac; - int32 mq; }; +#define HIST_API 0x40000000 +#define HIST_PI 0x20000000 +#define HIST_PC 0x10000000 +#define HIST_MIN 64 +#define HIST_MAX 65536 +#define HIST_M_LVL 0x3F +#define HIST_V_LVL 6 -#define XVM (cpu_unit.flags & UNIT_XVM) -#define RELOC (cpu_unit.flags & UNIT_RELOC) -#define PROT (cpu_unit.flags & UNIT_PROT) +typedef struct { + int32 pc; + int32 ir; + int32 ir1; + int32 lac; + int32 mq; + } InstHistory; + +#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 +#define EAE_DFLT UNIT_NOEAE #else -#define EAE_DFLT 0 +#define EAE_DFLT 0 #endif #if defined (PDP4) || defined (PDP7) -#define API_DFLT UNIT_NOAPI -#define PROT_DFLT 0 -#define ASW_DFLT 017763 +#define API_DFLT UNIT_NOAPI +#define PROT_DFLT 0 +#define ASW_DFLT 017763 #else -#define API_DFLT 0 -#define PROT_DFLT UNIT_PROT -#define ASW_DFLT 017720 +#define API_DFLT 0 +#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 */ +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 */ +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 */ +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 */ +int32 pcq[PCQ_SIZE] = { 0 }; /* PC queue */ #else -int16 pcq[PCQ_SIZE] = { 0 }; /* PC queue */ +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 */ -struct InstHistory *hst = NULL; /* instruction history */ +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 */ +InstHistory *hst = NULL; /* 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 int32 sim_brk_types, sim_brk_dflt, sim_brk_summ; /* breakpoint info */ extern DEVICE *sim_devices[]; extern FILE *sim_log; @@ -391,7 +391,7 @@ 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) & DMASK +#define INDEX(i,x) if (!memm && ((i) & I_IDX)) x = ((x) + XR) & DMASK int32 Prot15 (int32 ma, t_bool bndchk); int32 Reloc15 (int32 ma, int32 acc); int32 RelocXVM (int32 ma, int32 acc); @@ -402,9 +402,9 @@ extern t_stat fp15 (int32 ir); extern int32 clk (int32 dev, int32 pulse, int32 AC); -int32 (*dev_tab[DEV_MAX])(int32 dev, int32 pulse, int32 AC); /* device dispatch */ +int32 (*dev_tab[DEV_MAX])(int32 dev, int32 pulse, int32 AC); /* device dispatch */ -int32 (*dev_iors[DEV_MAX])(void); /* IORS 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, @@ -422,138 +422,144 @@ static const int32 api_ffo[256] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 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 */ - + { 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 + 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) }; +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) }, + { 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) }, + { 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) }, + { 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) }, + { 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 } }; + { 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 }, + { 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 }, + { 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 }, + { 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 }, + { UNIT_MSIZE, 4096, NULL, "4K", &cpu_set_size }, #endif - { UNIT_MSIZE, 8192, NULL, "8K", &cpu_set_size }, + { 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 }, + { 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 }, + { 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|MTAB_SHP, 0, "HISTORY", "HISTORY", - &cpu_set_hist, &cpu_show_hist }, - { 0 } }; + { MTAB_XTD|MTAB_VDV|MTAB_NMO|MTAB_SHP, 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 }; - + "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; @@ -561,259 +567,285 @@ 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 */ +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 */ +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 */ +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; +while (reason == 0) { /* loop until halted */ -if (sim_interval <= 0) { /* check clock queue */ - if (reason = sim_process_event ()) break; - api_int = api_eval (&int_pend); } /* eval API */ + 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 */ + 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 */ + + 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; } + 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 */ -#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 */ + 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 (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 (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 */ + 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 */ + 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 */ + 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 */ -#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_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; + 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 */ -#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> */ + + 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; + 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; + 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; - + 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; + 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; + 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; + 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; - + 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; + 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; + 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 */ + 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 */ + ion_defer = 1; /* defer intr */ #endif - goto xct_instr; /* go execute */ - + 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 @@ -821,208 +853,211 @@ case 020: /* XCT, dir */ 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 */ + 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); } + 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; + 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" */ + 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) & AMASK; - break; + MB = Jms_word (api_usmd | usmd); /* save state */ + if (Write (MA, MB, WR)) break; + PC = Incr_addr (MA) & AMASK; + 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 & AMASK; - break; - + case 031: /* JMP, indir */ + if (Ia (MA, &MA, 1)) break; + case 030: /* JMP, dir */ + INDEX (IR, MA); + PCQ_ENTRY; /* save old PC */ + PC = MA & AMASK; + break; + /* OPR: opcode 74 */ -case 037: /* OPR, indir */ - LAC = (LAC & LINK) | IR; /* LAW */ - break; + 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 */ + 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 */ - 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 */ + 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 */ - if (IR & 0000004) { /* OAS */ + 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 */ + if (usmd) prvn = trap_pending = 1; /* trap if usmd */ + else if (!api_usmd) /* nop if api_usmd */ #endif - LAC = LAC | SR; } + 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 */ + 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 */ + 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 */ + 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 */ - 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 @@ -1033,426 +1068,461 @@ case 036: /* OPR, dir */ 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 */ + 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> */ - 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 + 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; - Multiply uses a shift and add algorithm. The PDP-15, unlike prior +/* 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 */ + 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)) { + if ((IR & 0004000) && (eae_ac_sign ^ link_init)) { #else - if (eae_ac_sign ^ link_init) { /* result negative? */ + if (eae_ac_sign ^ link_init) { /* result negative? */ #endif - LAC = LAC ^ DMASK; - MQ = MQ ^ DMASK; } - break; + 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.*/ + 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 */ + 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)) + if ((IR & 0004000) && (eae_ac_sign ^ link_init)) #else - if (eae_ac_sign ^ link_init) /* result negative? */ + if (eae_ac_sign ^ link_init) /* result negative? */ #endif - MQ = MQ ^ DMASK; - break; - -/* EAE, continued + MQ = MQ ^ DMASK; + break; - EAE shifts, whether left or right, fill from the link. If the +/* 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 */ + case 4: /* normalize */ #if defined (PDP15) - if (!usmd) ion_defer = 2; /* free instructions */ + 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; + 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 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 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 */ - 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 */ + 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 */ + t = (IR & 0400)? (IR | 0777000): (IR & 0377); /* sext immediate */ + switch ((IR >> 9) & 017) { /* case on IR<5:8> */ + 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 + 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 */ + 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 */ + case 034: /* IOT */ #if defined (PDP15) - if (IR & 0010000) { /* floating point? */ - reason = fp15 (IR); /* process */ - break; } + 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 */ + 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 (device, pulse, iot_data); - break; + 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 (device, 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 (device, 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; + 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 (device, 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 (device, 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; + 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 (device, 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 (device, 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; + 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 (device, 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] (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 */ - + default: /* devices */ + if (dev_tab[device]) /* defined? */ + iot_data = dev_tab[device] (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 */ +iors = upd_iors (); /* get IORS */ +pcq_r->qptr = pcq_p; /* update pc q ptr */ return reason; } @@ -1462,18 +1532,20 @@ int32 api_eval (int32 *pend) { int32 i, hi; -*pend = 0; /* assume no intr */ -#if defined (PDP15) /* PDP15 only */ -if (ion_inh) return 0; /* inhibited? */ +*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 */ +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; } @@ -1484,22 +1556,22 @@ 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 */ +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. */ + 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) { @@ -1521,16 +1593,18 @@ t_stat Ia (int32 ma, int32 *ea, t_bool jmp) int32 t; t_stat sta = MM_OK; -if ((ma & B_DAMASK & ~07) == 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 */ +if ((ma & B_DAMASK & ~07) == 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; } @@ -1542,40 +1616,45 @@ 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)); + ((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. */ + 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; } +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; } @@ -1583,14 +1662,17 @@ 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 */ + 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; } @@ -1599,21 +1681,24 @@ t_stat Ia (int32 ma, int32 *ea, t_bool jmp) int32 t; t_stat sta = MM_OK; -if ((ma & B_DAMASK & ~07) == 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); } +if ((ma & B_DAMASK & ~07) == 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 */ +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; } @@ -1625,38 +1710,42 @@ 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)); + ((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. - Read and write mask addresses to 17b except for XVM systems */ + 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. + Read and write mask addresses to 17b except for XVM systems */ 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); /* PDP-15 prot, fetch only */ - 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; } +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); /* PDP-15 prot, fetch only */ + 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; } @@ -1664,14 +1753,15 @@ 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); /* PDP-15 prot, !defer */ - 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 */ +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); /* PDP-15 prot, !defer */ + 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; } @@ -1684,22 +1774,24 @@ int32 damask = memm? B_DAMASK: P_DAMASK; static const int32 g_mask[4] = { MM_G_W0, MM_G_W1, MM_G_W2, MM_G_W3 }; 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); } +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; } -gmode = MM_GETGM (MMR); /* get G_mode */ -if (usmd && XVM && gmode) { /* XVM user mode? */ - *ea = t & g_mask[gmode]; } /* mask ia to size */ -else if ((ma & damask & ~07) == 010) *ea = t & DMASK; /* autoindex? */ -else *ea = (PC & BLKMASK) | (t & IAMASK); /* within 32K */ +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; + } +gmode = MM_GETGM (MMR); /* get G_mode */ +if (usmd && XVM && gmode) /* XVM user mode? */ + *ea = t & g_mask[gmode]; /* mask ia to size */ +else if ((ma & damask & ~07) == 010) *ea = t & DMASK; /* autoindex? */ +else *ea = (PC & BLKMASK) | (t & IAMASK); /* within 32K */ return sta; } @@ -1715,21 +1807,23 @@ 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)); + ((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 */ +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) */ @@ -1738,14 +1832,16 @@ 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; } +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; } @@ -1757,30 +1853,37 @@ int32 pa, gmode, slr; 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 */ -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; } +gmode = MM_GETGM (MMR); /* get G_mode */ +slr = MM_GETSLR (MMR); /* get segment length */ +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) @@ -1810,9 +1913,10 @@ 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 ((int32) addr < 0) return STOP_MME; } + if (XVM) addr = RelocXVM (addr, REL_C); + else if (RELOC) addr = Reloc15 (addr, REL_C); + if ((int32) addr < 0) return STOP_MME; + } #endif if (addr >= MEMSIZE) return SCPE_NXM; if (vptr != NULL) *vptr = M[addr] & DMASK; @@ -1825,9 +1929,10 @@ 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 ((int32) addr < 0) return STOP_MME; } + if (XVM) addr = RelocXVM (addr, REL_C); + else if (RELOC) addr = Reloc15 (addr, REL_C); + if ((int32) addr < 0) return STOP_MME; + } #endif if (addr >= MEMSIZE) return SCPE_NXM; M[addr] = val & DMASK; @@ -1842,10 +1947,10 @@ int32 mc = 0; uint32 i; if ((val <= 0) || (val > MAXMEMSIZE) || ((val & 07777) != 0)) - return SCPE_ARG; + 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; + return SCPE_OK; MEMSIZE = val; for (i = MEMSIZE; i < MAXMEMSIZE; i++) M[i] = 0; return SCPE_OK; @@ -1866,9 +1971,9 @@ 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 */ +newdev = get_uint (cptr, 8, DEV_MAX - 1, &r); /* get new */ if ((r != SCPE_OK) || (newdev == dibp->dev)) return r; -dibp->dev = newdev; /* store */ +dibp->dev = newdev; /* store */ return SCPE_OK; } @@ -1893,7 +1998,7 @@ return SCPE_OK; int32 bad_dev (int32 dev, int32 pulse, int32 AC) { -return (SCPE_IERR << IOT_V_REASON) | AC; /* broken! */ +return (SCPE_IERR << IOT_V_REASON) | AC; /* broken! */ } /* Build device dispatch table */ @@ -1905,36 +2010,38 @@ DIB *dibp; uint32 i, j, p; static const uint8 std_dev[] = #if defined (PDP4) - { 000 }; + { 000 }; #elif defined (PDP7) - { 000, 033, 077 }; + { 000, 033, 077 }; #else - { 000, 017, 033, 055, 077 }; + { 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 */ +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; } @@ -1946,20 +2053,23 @@ int32 i, lnt; t_stat r; if (cptr == NULL) { - for (i = 0; i < hst_lnt; i++) hst[i].pc = 0; - hst_p = 0; - return SCPE_OK; } + for (i = 0; i < hst_lnt; i++) hst[i].pc = 0; + hst_p = 0; + return SCPE_OK; + } lnt = (int32) get_uint (cptr, 10, HIST_MAX, &r); if ((r != SCPE_OK) || (lnt && (lnt < HIST_MIN))) return SCPE_ARG; hst_p = 0; if (hst_lnt) { - free (hst); - hst_lnt = 0; - hst = NULL; } + free (hst); + hst_lnt = 0; + hst = NULL; + } if (lnt) { - hst = calloc (sizeof (struct InstHistory), lnt); - if (hst == NULL) return SCPE_MEM; - hst_lnt = lnt; } + hst = (InstHistory *) calloc (lnt, sizeof (InstHistory)); + if (hst == NULL) return SCPE_MEM; + hst_lnt = lnt; + } return SCPE_OK; } @@ -1971,38 +2081,39 @@ int32 l, j, k, di, lnt; char *cptr = (char *) desc; t_value sim_eval[2]; t_stat r; -struct InstHistory *h; +InstHistory *h; extern t_stat fprint_sym (FILE *ofile, t_addr addr, t_value *val, - UNIT *uptr, int32 sw); + UNIT *uptr, int32 sw); -if (hst_lnt == 0) return SCPE_NOFNC; /* enabled? */ +if (hst_lnt == 0) return SCPE_NOFNC; /* enabled? */ if (cptr) { - lnt = (int32) get_uint (cptr, 10, hst_lnt, &r); - if ((r != SCPE_OK) || (lnt == 0)) return SCPE_ARG; } + lnt = (int32) get_uint (cptr, 10, hst_lnt, &r); + if ((r != SCPE_OK) || (lnt == 0)) return SCPE_ARG; + } else lnt = hst_lnt; -di = hst_p - lnt; /* work forward */ +di = hst_p - lnt; /* work forward */ if (di < 0) di = di + hst_lnt; fprintf (st, "PC L AC MQ IR\n\n"); -for (k = 0; k < lnt; k++) { /* print specified */ - h = &hst[(di++) % hst_lnt]; /* entry pointer */ - if (h->pc & HIST_PC) { /* instruction? */ - l = (h->lac >> 18) & 1; /* link */ - fprintf (st, "%06o %o %06o %06o ", h->pc & AMASK, l, h->lac & DMASK, h->mq); - sim_eval[0] = h->ir; - sim_eval[1] = h->ir1; - if ((fprint_sym (st, h->pc & AMASK, sim_eval, &cpu_unit, SWMASK ('M'))) > 0) - fprintf (st, "(undefined) %06o", h->ir); - } /* end else instruction */ - else 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 continue; /* invalid */ - fputc ('\n', st); /* end line */ - } /* end for */ +for (k = 0; k < lnt; k++) { /* print specified */ + h = &hst[(di++) % hst_lnt]; /* entry pointer */ + if (h->pc & HIST_PC) { /* instruction? */ + l = (h->lac >> 18) & 1; /* link */ + fprintf (st, "%06o %o %06o %06o ", h->pc & AMASK, l, h->lac & DMASK, h->mq); + sim_eval[0] = h->ir; + sim_eval[1] = h->ir1; + if ((fprint_sym (st, h->pc & AMASK, sim_eval, &cpu_unit, SWMASK ('M'))) > 0) + fprintf (st, "(undefined) %06o", h->ir); + } /* end else instruction */ + else 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 continue; /* invalid */ + fputc ('\n', st); /* end line */ + } /* end for */ return SCPE_OK; } @@ -2015,7 +2126,7 @@ t_value word; hst[hst_p].pc = addr | HIST_PC; hst[hst_p].ir = inst; if (cpu_ex (&word, (addr + 1) & AMASK, &cpu_unit, SWMASK ('V'))) - hst[hst_p].ir1 = 0; + hst[hst_p].ir1 = 0; else hst[hst_p].ir1 = word; hst[hst_p].lac = LAC; hst[hst_p].mq = MQ; @@ -2031,7 +2142,7 @@ 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].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; diff --git a/PDP18B/pdp18b_defs.h b/PDP18B/pdp18b_defs.h index d53ffba5..7f451415 100644 --- a/PDP18B/pdp18b_defs.h +++ b/PDP18B/pdp18b_defs.h @@ -1,6 +1,6 @@ /* pdp18b_defs.h: 18b PDP simulator definitions - Copyright (c) 1993-2004, Robert M Supnik + Copyright (c) 1993-2005, 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"), @@ -19,28 +19,28 @@ 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 + 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. - 14-Jan-04 RMS Revised IO device call interface - 18-Oct-03 RMS Added DECtape off reel message - 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 + 14-Jan-04 RMS Revised IO device call interface + 18-Oct-03 RMS Added DECtape off reel message + 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 @@ -48,230 +48,228 @@ */ #ifndef _PDP18B_DEFS_H_ -#define _PDP18B_DEFS_H_ 0 +#define _PDP18B_DEFS_H_ 0 -#include "sim_defs.h" /* simulator defns */ +#include "sim_defs.h" /* simulator defns */ /* Models: only one should be defined - model memory CPU options I/O options + 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 + 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 + 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 additional Teletypes + 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 additional Teletypes - 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/LT19 additional Teletypes + 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/LT19 additional Teletypes ??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 */ +#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 */ -#define STOP_DTOFF 9 /* DECtape off reel */ +#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 */ +#define STOP_DTOFF 9 /* DECtape off reel */ /* 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 */ +#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 */ +#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 4 /* second Teletype(s) */ -#define BRMASK 0076000 /* bounds mask */ +#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 4 /* second Teletype(s) */ +#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 16 /* second Teletype(s) */ -#define BRMASK 0377400 /* bounds mask */ -#define BRMASK_XVM 0777400 /* bounds mask, XVM */ +#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 16 /* second Teletype(s) */ +#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) +#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) +#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 +#define FE 0 +#define DF 1 +#define RD 2 +#define WR 3 /* Memory status codes */ -#define MM_OK 0 -#define MM_ERR 1 +#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 */ +#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 */ +#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 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 */ +#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 +#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) - +#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 */ +#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 dev, int32 pulse, int32 dat); -}; - -typedef struct pdp18b_dib DIB; +typedef struct { + uint32 dev; /* base dev number */ + uint32 num; /* number of slots */ + int32 (*iors)(void); /* IORS responder */ + int32 (*dsp[DEV_MAXBLK])(int32 dev, int32 pulse, int32 dat); + } 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 */ - +#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 @@ -279,210 +277,210 @@ typedef struct pdp18b_dib DIB; 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 + 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 - + 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 - On the PDP-9, any API level active masks PI, and PI does not mask API. On the PDP-15, only the hardware API levels active mask PI, and PI masks the API software levels. */ -#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 */ +#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) +#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) +#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 */ +#define API_HLVL 4 /* hwre levels */ +#define ACH_SWRE 040 /* swre int vec */ /* API level 0 */ -#define INT_V_PWRFL 0 /* powerfail */ +#define INT_V_PWRFL 0 /* powerfail */ -#define INT_PWRFL (1 << INT_V_PWRFL) +#define INT_PWRFL (1 << INT_V_PWRFL) -#define API_PWRFL 0 +#define API_PWRFL 0 -#define ACH_PWRFL 052 +#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_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 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 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 +#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_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 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 API_PTR 2 +#define API_LPT 2 +#define API_LPTSPC 2 -#define ACH_PTR 050 -#define ACH_LPT 056 +#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_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 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 API_CLK 3 +#define API_TTI1 3 +#define API_TTO1 3 -#define ACH_CLK 051 -#define ACH_TTI1 075 -#define ACH_TTO1 074 +#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_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 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 +#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) - +#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 + 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* + 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 */ +#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 */ +#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 */ +#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 */ +#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 */ @@ -491,4 +489,3 @@ 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_diag.txt b/PDP18B/pdp18b_diag.txt index 0055c4ee..ea0dadcd 100644 --- a/PDP18B/pdp18b_diag.txt +++ b/PDP18B/pdp18b_diag.txt @@ -55,4 +55,4 @@ MAINDEC-15-D1CD-PB Extended memory test Read in: 200 (ignored, binary tape) Start: 200 Halts after printout, set SR = 30000 -Breakpoint: 563 for one pass \ No newline at end of file +Breakpoint: 563 for one pass diff --git a/PDP18B/pdp18b_doc.txt b/PDP18B/pdp18b_doc.txt index 8b16c0c2..f9c5c124 100644 --- a/PDP18B/pdp18b_doc.txt +++ b/PDP18B/pdp18b_doc.txt @@ -1,14 +1,14 @@ To: Users From: Bob Supnik Subj: 18b PDP Simulator Usage -Date: 15-Nov-2004 +Date: 01-Jul-2005 COPYRIGHT NOTICE The following copyright notice applies to both the SIMH source and binary: - Original code published in 1993-2004, written by Robert M Supnik - Copyright (c) 1993-2004, Robert M Supnik + Original code published in 1993-2005, written by Robert M Supnik + Copyright (c) 1993-2005, 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"), @@ -27,8 +27,8 @@ The following copyright notice applies to both the SIMH source and binary: 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 + 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. @@ -569,8 +569,7 @@ 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. +active connections. The SET TTIXn DISCONNECT command disconnects line n. The input device (TTIX) implements these registers: diff --git a/PDP18B/pdp18b_drm.c b/PDP18B/pdp18b_drm.c index ef97ac7d..7ed60f5b 100644 --- a/PDP18B/pdp18b_drm.c +++ b/PDP18B/pdp18b_drm.c @@ -1,6 +1,6 @@ /* pdp18b_drm.c: drum/fixed head disk simulator - Copyright (c) 1993-2004, Robert M Supnik + Copyright (c) 1993-2005, 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"), @@ -19,23 +19,23 @@ 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 + 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 + drm (PDP-4,PDP-7) Type 24 serial drum - 14-Jan-04 RMS Revised IO device call interface - 26-Oct-03 RMS Cleaned up buffer copy code - 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 + 14-Jan-04 RMS Revised IO device call interface + 26-Oct-03 RMS Cleaned up buffer copy code + 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" @@ -43,33 +43,33 @@ /* 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 */ +#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 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))) -#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 */ +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 dev, int32 pulse, int32 AC); @@ -82,47 +82,52 @@ 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 + 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) }; +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 } }; + { 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 } }; + { 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 }; - + "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 dev, 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 */ +if ((pulse & 027) == 06) { /* DRLR, DRLW */ + drm_ma = AC & 0177777; /* load mem addr */ + drm_unit.FUNC = pulse & DRM_WRITE; /* save function */ + } return AC; } @@ -130,16 +135,19 @@ int32 drm61 (int32 dev, 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 */ +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; } @@ -147,17 +155,19 @@ int32 drm62 (int32 dev, 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 */ +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. @@ -169,33 +179,38 @@ int32 i; uint32 da; int32 *fbuf = uptr->filebuf; -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); } +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) { /* read? */ - if (MEM_ADDR_OK (drm_ma)) /* if !nxm */ - M[drm_ma] = fbuf[da]; } /* read word */ - else { /* write */ - if ((drm_wlk >> (drm_da >> 4)) & 1) drm_err = 1; - else { /* not locked */ - fbuf[da] = M[drm_ma]; /* write word */ - 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 */ +da = drm_da * DRM_NUMWDS; /* compute dev addr */ +for (i = 0; i < DRM_NUMWDS; i++, da++) { /* do transfer */ + if (uptr->FUNC == DRM_READ) { /* read? */ + if (MEM_ADDR_OK (drm_ma)) /* if !nxm */ + M[drm_ma] = fbuf[da]; /* read word */ + } + else { /* write */ + if ((drm_wlk >> (drm_da >> 4)) & 1) drm_err = 1; + else { /* not locked */ + fbuf[da] = M[drm_ma]; /* write word */ + 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 */ +CLR_INT (DRM); /* clear done */ sim_cancel (&drm_unit); return SCPE_OK; } @@ -213,20 +228,20 @@ return (TST_INT (DRM)? IOS_DRM: 0); #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 */ -}; + 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? */ +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 index 153198b9..367ab893 100644 --- a/PDP18B/pdp18b_dt.c +++ b/PDP18B/pdp18b_dt.c @@ -1,6 +1,6 @@ /* pdp18b_dt.c: 18b DECtape simulator - Copyright (c) 1993-2004, Robert M Supnik + Copyright (c) 1993-2005, 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"), @@ -19,46 +19,47 @@ 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 + 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 + dt (PDP-4, PDP-7) Type 550/555 DECtape + (PDP-9) TC02/TU55 DECtape + (PDP-15) TC15/TU56 DECtape - 25-Jan-04 RMS Revised for device debug support - 14-Jan-04 RMS Revised IO device call interface - Changed sim_fsize calling sequence, added STOP_OFFR - 26-Oct-03 RMS Cleaned up buffer copy code - 18-Oct-03 RMS Fixed reverse checksum in read all - Added DECtape off reel message - Simplified timing - 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 + 16-Aug-05 RMS Fixed C++ declaration and cast problems + 25-Jan-04 RMS Revised for device debug support + 14-Jan-04 RMS Revised IO device call interface + Changed sim_fsize calling sequence, added STOP_OFFR + 26-Oct-03 RMS Cleaned up buffer copy code + 18-Oct-03 RMS Fixed reverse checksum in read all + Added DECtape off reel message + Simplified timing + 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] + 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. @@ -66,13 +67,13 @@ Tape density is nominally 300 lines per inch. The format of a DECtape (as taken from the TD8E formatter) is: - reverse end zone 8192 reverse end zone codes ~ 10 feet - reverse buffer 200 interblock codes - block 0 - : - block n - forward buffer 200 interblock codes - forward end zone 8192 forward end zone codes ~ 10 feet + reverse end zone 8192 reverse end zone codes ~ 10 feet + reverse buffer 200 interblock codes + block 0 + : + block n + forward buffer 200 interblock codes + forward end zone 8192 forward end zone codes ~ 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 @@ -86,15 +87,15 @@ 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 checksum (for reverse reads) - : - trailer word 4 checksum (for forward reads) - trailer words 3,2 0 - trailer word 1 block number (for reverse reads) - trailer word 0 0 + header word 0 0 + header word 1 block number (for forward reads) + header words 2,3 0 + header word 4 checksum (for reverse reads) + : + trailer word 4 checksum (for forward reads) + 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. @@ -107,218 +108,218 @@ #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 */ +#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_LPERMC 6 /* lines per mark track */ -#define DT_BLKWD 1 /* blk no word in h/t */ -#define DT_CSMWD 4 /* checksum word in h/t */ -#define DT_HTWRD 5 /* header/trailer words */ -#define DT_EZLIN (8192 * DT_LPERMC) /* end zone length */ -#define DT_BFLIN (200 * DT_LPERMC) /* buffer length */ -#define DT_BLKLN (DT_BLKWD * DT_LPERMC) /* blk no line in h/t */ -#define DT_CSMLN (DT_CSMWD * DT_LPERMC) /* csum line in h/t */ -#define DT_HTLIN (DT_HTWRD * DT_LPERMC) /* header/trailer lines */ +#define DT_LPERMC 6 /* lines per mark track */ +#define DT_BLKWD 1 /* blk no word in h/t */ +#define DT_CSMWD 4 /* checksum word in h/t */ +#define DT_HTWRD 5 /* header/trailer words */ +#define DT_EZLIN (8192 * DT_LPERMC) /* end zone length */ +#define DT_BFLIN (200 * DT_LPERMC) /* buffer length */ +#define DT_BLKLN (DT_BLKWD * DT_LPERMC) /* blk no line in h/t */ +#define DT_CSMLN (DT_CSMWD * DT_LPERMC) /* csum line in h/t */ +#define DT_HTLIN (DT_HTWRD * DT_LPERMC) /* header/trailer lines */ /* 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)) +#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_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)) +#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 +#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 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)) +#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); +#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); +#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) +#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) +#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) +#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_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) + ((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) + ((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 */ +#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 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)) -#define ABS(x) (((x) < 0)? (-(x)): (x)) - extern int32 M[]; extern int32 int_hwre[API_HLVL+1]; extern UNIT cpu_unit; @@ -326,17 +327,18 @@ extern int32 sim_switches; extern int32 sim_is_running; extern FILE *sim_deb; -int32 dtsa = 0; /* status A */ -int32 dtsb = 0; /* status B */ -int32 dtdb = 0; /* data buffer */ -int32 dt_ltime = 12; /* interline time */ -int32 dt_dctime = 40000; /* decel time */ +int32 dtsa = 0; /* status A */ +int32 dtsb = 0; /* status B */ +int32 dtdb = 0; /* data buffer */ +int32 dt_ltime = 12; /* interline time */ +int32 dt_dctime = 40000; /* decel time */ int32 dt_substate = 0; int32 dt_logblk = 0; -int32 dt_stopoffr = 0; /* stop on off reel */ -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 }; +int32 dt_stopoffr = 0; /* stop on off reel */ +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 dev, int32 pulse, int32 dat); @@ -358,142 +360,151 @@ 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 + 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) } }; + { 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) }, + { 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) }, + { FLDATA (ENB, dtsa, DTA_V_ENB) }, #endif - { FLDATA (DTF, dtsb, DTB_V_DTF) }, + { FLDATA (DTF, dtsb, DTB_V_DTF) }, #if defined (DTB_V_BEF) - { FLDATA (BEF, dtsb, 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) }, + { 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 (DCTIME, dt_dctime, 31), REG_NZ }, - { ORDATA (SUBSTATE, dt_substate, 2) }, - { 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 }, - { FLDATA (STOP_OFFR, dt_stopoffr, 0) }, - { NULL } }; + { DRDATA (LTIME, dt_ltime, 31), REG_NZ }, + { DRDATA (DCTIME, dt_dctime, 31), REG_NZ }, + { ORDATA (SUBSTATE, dt_substate, 2) }, + { 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 }, + { FLDATA (STOP_OFFR, dt_stopoffr, 0) }, + { 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 } }; + { 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 } + }; DEBTAB dt_deb[] = { - { "MOTION", LOG_MS }, - { "DATA", LOG_RW }, - { "READALL", LOG_RA }, - { "BLOCK", LOG_BL }, - { NULL, 0 } }; + { "MOTION", LOG_MS }, + { "DATA", LOG_RW }, + { "READALL", LOG_RA }, + { "BLOCK", LOG_BL }, + { 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, - &dt_dib, DEV_DISABLE | DEV_DEBUG, 0, - dt_deb, NULL, NULL }; - + "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 | DEV_DEBUG, 0, + dt_deb, NULL, NULL + }; + /* IOT routines */ -#if defined (TC02) /* TC02/TC15 */ +#if defined (TC02) /* TC02/TC15 */ int32 dt75 (int32 dev, 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); +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 dev, int32 pulse, int32 dat) { -if ((pulse & 01) && (dtsb & DTB_DTF)) /* DTDF */ - return IOT_SKP + dat; +if ((pulse & 01) && (dtsb & DTB_DTF)) /* DTDF */ + return IOT_SKP + dat; return dat; } -#else /* Type 550 */ +#else /* Type 550 */ int32 dt75 (int32 dev, 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); } +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; } @@ -503,38 +514,42 @@ int32 dt76 (int32 dev, 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); } +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) @@ -542,36 +557,36 @@ 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_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); +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 + - schedule acceleration + - set function as next state 2. If change in motion, start to stop - - if not already decelerating (could be reversing), - schedule deceleration + - 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 + - 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 + - schedule acceleration + - set function as next state 5. If not yet at speed, - - set function as next state + - set function as next state 6. If at speed, - - set function as current state, schedule function + - set function as current state, schedule function */ void dt_newsa (int32 newf) @@ -580,63 +595,71 @@ 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? */ +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 ((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 ((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_dctime - (dt_dctime >> 2)); /* sched accel */ - DTS_SETSTA (DTS_ACCF | new_dir, 0); /* state = accel */ - DTS_SET2ND (DTS_ATSF | new_dir, new_fnc); /* next = fnc */ - return; } +if (new_mving & ~prev_mving) { /* start? */ + if (dt_setpos (uptr)) return; /* update pos */ + sim_cancel (uptr); /* stop current */ + sim_activate (uptr, dt_dctime - (dt_dctime >> 2)); /* sched 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_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_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_dctime - (dt_dctime >> 2)); /* sched 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_ACCF) { /* not accel/at speed? */ + if (dt_setpos (uptr)) return; /* update pos */ + sim_cancel (uptr); /* cancel cur */ + sim_activate (uptr, dt_dctime - (dt_dctime >> 2)); /* sched 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; } +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; +return; } - + /* Schedule new DECtape function This routine is only called if @@ -651,99 +674,117 @@ return; void dt_newfnc (UNIT *uptr, int32 newsta) { -int32 fnc, dir, blk, unum, relpos, newpos; +int32 fnc, dir, blk, unum, newpos; +#if defined (TC02) +int32 relpos; +#endif 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 */ +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); +unum = (int32) (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 (DEBUG_PRI (dt_dev, LOG_MS)) fprintf (sim_deb, ">>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 (DEBUG_PRI (dt_dev, LOG_MS)) fprintf (sim_deb, ">>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; +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 (DEBUG_PRI (dt_dev, LOG_MS)) fprintf (sim_deb, ">>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 (DEBUG_PRI (dt_dev, LOG_MS)) fprintf (sim_deb, ">>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 (DEBUG_PRI (dt_dev, LOG_RA) || - (DEBUG_PRI (dt_dev, LOG_BL) && (blk == dt_logblk))) - fprintf (sim_deb, ">>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; } + + 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 (DEBUG_PRI (dt_dev, LOG_RA) || + (DEBUG_PRI (dt_dev, LOG_BL) && (blk == dt_logblk))) + fprintf (sim_deb, ">>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) + 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) + 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. @@ -755,40 +796,47 @@ 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_dctime - (dt_dctime >> 2)) / 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 */ +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_dctime - (dt_dctime >> 2)) / 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? */ + 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; } + unum = (int32) (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 @@ -799,8 +847,10 @@ t_stat dt_svc (UNIT *uptr) int32 mot = DTS_GETMOT (uptr->STATE); int32 dir = mot & DTS_DIR; int32 fnc = DTS_GETFNC (uptr->STATE); -int32 *fbuf = uptr->filebuf; +int32 *fbuf = (int32 *) uptr->filebuf; +#if defined (TC02) int32 unum = uptr - dt_dev.units; +#endif int32 blk, wrd, ma, relpos; uint32 ba; @@ -812,21 +862,26 @@ uint32 ba; */ switch (mot) { -case DTS_DECF: case DTS_DECR: /* decelerating */ - if (dt_setpos (uptr)) /* upd pos; off reel? */ - return IORETURN (dt_stopoffr, STOP_DTOFF); - uptr->STATE = DTS_NXTSTA (uptr->STATE); /* advance state */ - if (uptr->STATE) /* not stopped? */ - sim_activate (uptr, dt_dctime - (dt_dctime >> 2)); /* 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; } + + case DTS_DECF: case DTS_DECR: /* decelerating */ + if (dt_setpos (uptr)) /* upd pos; off reel? */ + return IORETURN (dt_stopoffr, STOP_DTOFF); + uptr->STATE = DTS_NXTSTA (uptr->STATE); /* advance state */ + if (uptr->STATE) /* not stopped? */ + sim_activate (uptr, dt_dctime - (dt_dctime >> 2)); /* 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 @@ -835,284 +890,319 @@ default: /* other */ Off reel - detach unit (it must be deselected) */ -if (dt_setpos (uptr)) /* upd pos; off reel? */ - return IORETURN (dt_stopoffr, STOP_DTOFF); -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; - +if (dt_setpos (uptr)) /* upd pos; off reel? */ + return IORETURN (dt_stopoffr, STOP_DTOFF); +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; +#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 + 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 + 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 + 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 (DEBUG_PRI (dt_dev, LOG_RW) || - (DEBUG_PRI (dt_dev, LOG_BL) && (blk == dt_logblk))) - fprintf (sim_deb, ">>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 = fbuf[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; - + 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 (DEBUG_PRI (dt_dev, LOG_RW) || + (DEBUG_PRI (dt_dev, LOG_BL) && (blk == dt_logblk))) + fprintf (sim_deb, ">>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 = fbuf[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; + } /* end case subst */ + 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 + 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 + 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 (DEBUG_PRI (dt_dev, LOG_RW) || - (DEBUG_PRI (dt_dev, LOG_BL) && (blk == dt_logblk))) - fprintf (sim_deb, ">>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 */ - fbuf[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; - + 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 (DEBUG_PRI (dt_dev, LOG_RW) || + (DEBUG_PRI (dt_dev, LOG_BL) && (blk == dt_logblk))) + fprintf (sim_deb, ">>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 */ + fbuf[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; + } /* end case subst */ + 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 + 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 = fbuf[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; + case FNC_RALL: /* read all */ + 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 = fbuf[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 + 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; - fbuf[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; - + case FNC_WALL: /* write all */ + 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; + fbuf[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; +#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 = fbuf[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; + 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 = fbuf[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) fbuf[ba] = dt_comobv (dtdb); /* get data word */ - else fbuf[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; + 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) fbuf[ba] = dt_comobv (dtdb); /* get data word */ + else fbuf[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 */ + default: + dt_seterr (uptr, DTB_SEL); /* impossible state */ + break; + } /* end case function */ + +DT_UPDINT; /* update interrupts */ return SCPE_OK; } - + /* Utility routines */ /* Set error flag */ @@ -1121,13 +1211,14 @@ 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 */ +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; } @@ -1138,8 +1229,8 @@ 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 */ +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; } @@ -1148,10 +1239,10 @@ return; int32 dt_comobv (int32 dat) { -dat = dat ^ DMASK; /* compl obverse */ +dat = dat ^ DMASK; /* compl obverse */ dat = ((dat >> 15) & 07) | ((dat >> 9) & 070) | - ((dat >> 3) & 0700) | ((dat & 0700) << 3) | - ((dat & 070) << 9) | ((dat & 07) << 15); + ((dat >> 3) & 0700) | ((dat & 0700) << 3) | + ((dat & 070) << 9) | ((dat & 07) << 15); return dat; } @@ -1159,23 +1250,25 @@ return dat; int32 dt_csum (UNIT *uptr, int32 blk) { -int32 *fbuf = uptr->filebuf; +int32 *fbuf = (int32 *) 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 = fbuf[ba + i] ^ DMASK; /* get ~word */ - csum = csum ^ (wrd >> 12) ^ (wrd >> 6) ^ wrd; } +#if defined (TC02) /* TC02/TC15 */ +csum = 077; /* init csum */ +for (i = 0; i < DTU_BSIZE (uptr); i++) { /* loop thru buf */ + wrd = fbuf[ba + i] ^ DMASK; /* get ~word */ + csum = csum ^ (wrd >> 12) ^ (wrd >> 6) ^ wrd; + } return (csum & 077); -#else /* Type 550 */ +#else /* Type 550 */ csum = 0777777; -for (i = 0; i < DTU_BSIZE (uptr); i++) { /* loop thru buf */ - wrd = fbuf[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 */ +for (i = 0; i < DTU_BSIZE (uptr); i++) { /* loop thru buf */ + wrd = fbuf[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 } @@ -1185,20 +1278,20 @@ 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 077; /* rev csum */ -#if defined (TC02) /* TC02/TC15 */ -if (wrd == ((2 * DT_HTWRD) + DTU_BSIZE (uptr) - DT_CSMWD - 1)) /* fwd csum */ - return (dt_csum (uptr, blk) << 12); +if (wrd == DT_BLKWD) return blk; /* fwd blknum */ +if (wrd == DT_CSMWD) return 077; /* rev csum */ +#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 == ((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 */ +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) @@ -1206,22 +1299,25 @@ 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 */ +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; } @@ -1235,7 +1331,7 @@ return ((dtsb & (DTB_ERF | DTB_DTF))? IOS_DTA: 0); return 0; #endif } - + /* Attach routine Determine 12b, 16b, or 18b/36b format @@ -1253,57 +1349,64 @@ uint32 ba, sz, k, *fbuf; 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 (uptr->fileref))) { - 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; } -fbuf = uptr->filebuf; /* file buffer */ +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 (uptr->fileref))) { + 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 (uint32)); +if (uptr->filebuf == NULL) { /* can't alloc? */ + detach_unit (uptr); + return SCPE_MEM; + } +fbuf = (uint32 *) 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 */ - fbuf[ba] = ((uint32) (pdp8b[k] & 07777) << 6) | - ((uint32) (pdp8b[k + 1] >> 6) & 077); - fbuf[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++) - fbuf[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 */ +if (uptr->flags & UNIT_8FMT) { /* 12b? */ + for (ba = 0; ba < uptr->capac; ) { /* loop thru file */ + k = fxread (pdp8b, sizeof (uint16), 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 */ + fbuf[ba] = ((uint32) (pdp8b[k] & 07777) << 6) | + ((uint32) (pdp8b[k + 1] >> 6) & 077); + fbuf[ba + 1] = ((uint32) (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 (uint16), D18_BSIZE, uptr->fileref); + if (k == 0) break; + for ( ; k < D18_BSIZE; k++) pdp11b[k] = 0; + for (k = 0; k < D18_BSIZE; k++) + fbuf[ba++] = pdp11b[k]; + } + uptr->hwmark = ba; + } /* end elif */ +else uptr->hwmark = fxread (uptr->filebuf, sizeof (uint32), + 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; } @@ -1325,40 +1428,46 @@ 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; } -fbuf = 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] = (fbuf[ba] >> 6) & 07777; - pdp8b[k + 1] = ((fbuf[ba] & 077) << 6) | - ((fbuf[ba + 1] >> 12) & 077); - pdp8b[k + 2] = fbuf[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] = fbuf[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 */ + 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; + } +fbuf = (uint32 *) 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] = (fbuf[ba] >> 6) & 07777; + pdp8b[k + 1] = ((fbuf[ba] & 077) << 6) | + ((fbuf[ba + 1] >> 12) & 077); + pdp8b[k + 2] = fbuf[ba + 1] & 07777; + ba = ba + 2; + } /* end loop blk */ + fxwrite (pdp8b, sizeof (uint16), 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] = fbuf[ba++] & 0177777; + fxwrite (pdp11b, sizeof (uint16), D18_BSIZE, uptr->fileref); + if (ferror (uptr->fileref)) break; + } /* end loop file */ + } /* end if 16b */ + else fxwrite (uptr->filebuf, sizeof (uint32), /* 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 index 01d3c935..eb6cc5e6 100644 --- a/PDP18B/pdp18b_fpp.c +++ b/PDP18B/pdp18b_fpp.c @@ -1,6 +1,6 @@ /* pdp18b_fpp.c: FP15 floating point processor simulator - Copyright (c) 2003-2004, Robert M Supnik + Copyright (c) 2003-2005, 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"), @@ -19,15 +19,15 @@ 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 + 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 + fpp PDP-15 floating point processor - 31-Oct-04 RMS Fixed URFST to mask low 9b of fraction - Fixed exception PC setting - 10-Apr-04 RMS JEA is 15b not 18b + 31-Oct-04 RMS Fixed URFST to mask low 9b of fraction + Fixed exception PC setting + 10-Apr-04 RMS JEA is 15b not 18b The FP15 instruction format is: @@ -71,75 +71,75 @@ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ */ - + #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) +#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 */ +#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 */ +#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 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)) +#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 }; + 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 { + int32 exp; /* exponent */ + int32 sign; /* sign */ + int32 hi; /* hi frac, 17b */ + int32 lo; /* lo frac, 18b */ + } UFP; -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 */ +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]; @@ -174,41 +174,43 @@ extern t_stat Read (int32 ma, int32 *dat, int32 cyc); extern t_stat Write (int32 ma, int32 dat, int32 cyc); 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 + 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, 15) }, - { FLDATA (STOP_FPP, stop_fpp, 0) }, - { NULL } }; + { 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, 15) }, + { 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 }; - + "FPP", &fpp_unit, fpp_reg, NULL, + 1, 8, 1, 1, 8, 18, + NULL, NULL, &fp15_reset, + NULL, NULL, NULL, + NULL, DEV_DISABLE + }; + /* Instruction decode for FP15 The CPU actually fetches the instruction and the word after. If the @@ -223,164 +225,176 @@ 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 */ +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 */ +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 */ +switch (fop) { /* case on subop */ -case FOP_TST: /* NOP */ - break; + 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_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_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_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_fdiv (fir, &fma, &fmb); /* yes, fp div */ - else sta = fp15_idiv (fir, &fma, &fmb); /* no, int div */ - break; + case FOP_DIV: /* divide */ + if (sta = fp15_opnd (fir, ar, &fmb)) break; /* fetch op to FMB */ + if (fir & FI_FP) /* fp? */ + sta = fp15_fdiv (fir, &fma, &fmb); /* yes, fp div */ + 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_fdiv (fir, &fma, &fmb); /* yes, fp div */ - 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_fdiv (fir, &fma, &fmb); /* yes, fp div */ + 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_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_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_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_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_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 & JEA_EAMASK; } - 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 & JEA_EAMASK; + } + 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_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; + 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; } + default: + break; + } /* end switch op */ -fma.exp = fma.exp & DMASK; /* mask exp to 18b */ +fma.exp = fma.exp & DMASK; /* mask exp to 18b */ fmb.exp = fmb.exp & DMASK; -if (sta != FP_OK) return fp15_exc (sta); /* error? */ +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; } - } +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; } @@ -389,62 +403,75 @@ 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 */ - if (ir & FI_DP) { /* dp? */ - wd[0] = a->exp & DMASK; /* exponent */ - wd[1] = (a->sign << 17) | a->hi; /* hi frac */ - wd[2] = a->lo; /* low frac */ - numwd = 3; } /* 3 words */ - 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? */ - wd[0] = (a->exp & 0777) | (a->lo & UFP_FL_SMASK); /* low frac'exp */ - wd[1] = (a->sign << 17) | a->hi; /* hi frac */ - numwd = 2; } /* 2 words */ - } -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? */ - 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; } - numwd = 2; } /* 2 words */ - else { /* single */ - if (a->hi || (a->lo & SIGN)) return FP_OVF; /* check int ovf */ - if (a->sign) wd[0] = fmb.lo; /* neg? store FMB */ - else wd[0] = a->lo; /* pos, store FMA */ - numwd = 1; } /* 1 word */ - } -for (i = 0; i < numwd; i++) { /* store words */ - if (Write (addr, wd[i], WR)) return FP_MM; - addr = (addr + 1) & AMASK; } +fguard = 0; /* clear guard */ +if (ir & FI_FP) { /* fp? */ + if (sta = fp15_norm (ir, a, NULL, 0)) return sta; /* normalize */ + if (ir & FI_DP) { /* dp? */ + wd[0] = a->exp & DMASK; /* exponent */ + wd[1] = (a->sign << 17) | a->hi; /* hi frac */ + wd[2] = a->lo; /* low frac */ + numwd = 3; /* 3 words */ + } + 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? */ + wd[0] = (a->exp & 0777) | (a->lo & UFP_FL_SMASK); /* low frac'exp */ + wd[1] = (a->sign << 17) | a->hi; /* hi frac */ + numwd = 2; /* 2 words */ + } + } +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? */ + 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; + } + numwd = 2; /* 2 words */ + } + else { /* single */ + if (a->hi || (a->lo & SIGN)) return FP_OVF; /* check int ovf */ + if (a->sign) wd[0] = fmb.lo; /* neg? store FMB */ + else wd[0] = a->lo; /* pos, store FMA */ + numwd = 1; /* 1 word */ + } + } +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 */ +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; } @@ -452,11 +479,11 @@ return FP_OK; 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 */ +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; } @@ -476,35 +503,40 @@ 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? */ - dp_swap (a, &fmq); /* quo = 0 (fmq), rem = a */ - 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 */ +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? */ + dp_swap (a, &fmq); /* quo = 0 (fmq), rem = a */ + 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 */ +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 @@ -515,39 +547,43 @@ 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); } } - } /* end if b != 0 */ -fp15_asign (ir, a); /* adjust A sign */ -return fp15_norm (ir, a, NULL, 0); /* norm, no round */ +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); + } + } + } /* 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 */ +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 */ @@ -556,23 +592,26 @@ 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 = 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 */ +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 = 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 */ @@ -581,26 +620,29 @@ 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 */ +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 */ +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; } @@ -608,8 +650,8 @@ return; void dp_inc (UFP *a) { -a->lo = (a->lo + 1) & UFP_FL_MASK; /* inc low */ -a->hi = a->hi + (a->lo == 0); /* propagate carry */ +a->lo = (a->lo + 1) & UFP_FL_MASK; /* inc low */ +a->hi = a->hi + (a->lo == 0); /* propagate carry */ return; } @@ -617,12 +659,14 @@ return; 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 */ +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 */ + a->lo = (b->lo - a->lo) & UFP_FL_MASK; /* b - a */ + a->sign = a->sign ^ 1; /* change a sign */ + } return; } @@ -643,14 +687,15 @@ void dp_mul (UFP *a, UFP *b) { int32 i; -fmq.hi = a->hi; /* FMQ <- a */ +fmq.hi = a->hi; /* FMQ <- a */ fmq.lo = a->lo; -a->hi = a->lo = 0; /* a <- 0 */ +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; +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 */ @@ -662,8 +707,9 @@ 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; } + b->hi = ((b->hi << 1) | (b->lo >> 17)) & UFP_FH_MASK; + b->lo = (b->lo << 1) & UFP_FL_MASK; + } return; } @@ -672,8 +718,9 @@ return; 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); } + 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; @@ -685,10 +732,10 @@ 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 */ +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; } @@ -698,7 +745,7 @@ void dp_swap (UFP *a, UFP *b) { int32 t; -t = a->hi; /* swap fractions */ +t = a->hi; /* swap fractions */ a->hi = b->hi; b->hi = t; t = a->lo; @@ -706,25 +753,26 @@ 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; } +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; } @@ -736,45 +784,52 @@ return; t_stat fp15_norm (int32 ir, UFP *a, UFP *b, t_bool rnd) { -a->hi = a->hi & UFP_FH_MASK; /* mask a */ +a->hi = a->hi & UFP_FH_MASK; /* mask a */ a->lo = a->lo & UFP_FL_MASK; -if (b) { /* if b, mask */ - b->hi = b->hi & UFP_FH_MASK; - b->lo = b->lo & UFP_FL_MASK; } -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? */ +if (b) { /* if b, mask */ + b->hi = b->hi & UFP_FH_MASK; + b->lo = b->lo & UFP_FL_MASK; + } +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 = (ma + 1) & IAMASK; /* new PC */ +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 = (ma + 1) & IAMASK; /* new PC */ return SCPE_OK; } - + /* Reset routine */ t_stat fp15_reset (DEVICE *dptr) diff --git a/PDP18B/pdp18b_lp.c b/PDP18B/pdp18b_lp.c index 99b1c3f7..505878b0 100644 --- a/PDP18B/pdp18b_lp.c +++ b/PDP18B/pdp18b_lp.c @@ -1,6 +1,6 @@ /* pdp18b_lp.c: 18b PDP's line printer simulator - Copyright (c) 1993-2004, Robert M Supnik + Copyright (c) 1993-2005, 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"), @@ -19,29 +19,29 @@ 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 + 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 + 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 - 14-Jan-04 RMS Revised IO device call interface - 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 + 14-Jan-04 RMS Revised IO device call interface + 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" @@ -51,29 +51,31 @@ extern int32 int_hwre[API_HLVL+1]; /* Type 62 line printer */ -#define LP62_BSIZE 120 /* line size */ -#define BPTR_MAX 40 /* pointer max */ -#define BPTR_MASK 077 /* buf ptr max */ +#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_spc = 0; /* print vs spc */ +int32 lp62_ovrpr = 0; /* overprint */ int32 lp62_stopioe = 0; -int32 lp62_bp = 0; /* buffer ptr */ +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','*','.','+',']','|','[' }; + ' ','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" }; + "\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 dev, int32 pulse, int32 dat); @@ -84,125 +86,137 @@ 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 + 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 }; + 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 } }; + { 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 } }; + { 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 }; - + "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 dev, int32 pulse, int32 dat) { int32 i; -if ((pulse & 01) && TST_INT (LPT)) dat = IOT_SKP | dat; /* LPSF */ +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 */ + 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 dev, 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 */ +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 + 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 */ +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 (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 */ +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; } @@ -210,34 +224,35 @@ return SCPE_OK; int32 lp62_iors (void) { -return (TST_INT (LPT)? IOS_LPT: 0) | - (TST_INT (LPTSPC)? IOS_LPT1: 0); +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 */ +#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_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 */ +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" }; + "\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 dev, int32 pulse, int32 dat); @@ -250,112 +265,128 @@ 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 + 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 }; + 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) }, + { 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) }, + { 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 } }; + { 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 } }; + { 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 }; - + "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 dev, 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 */ +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 */ + 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 */ - } + 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 dev, 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 & 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 ((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); } + 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 + 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) @@ -364,46 +395,51 @@ 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 */ +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 */ +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; } @@ -421,7 +457,7 @@ 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 */ +lp647_err = (lp647_unit.flags & UNIT_ATT)? 0: 1; /* clr/set error */ return reason; } @@ -434,16 +470,16 @@ return detach_unit (uptr); } #endif - + #if defined (LP09) /* LP09 line printer */ -#define LP09_BSIZE 132 /* line size */ +#define LP09_BSIZE 132 /* line size */ -int32 lp09_don = 0; /* ready */ -int32 lp09_err = 0; /* error */ -int32 lp09_ie = 1; /* int enable */ +int32 lp09_don = 0; /* ready */ +int32 lp09_err = 0; /* error */ +int32 lp09_ie = 1; /* int enable */ int32 lp09_stopioe = 0; DEVICE lp09_dev; @@ -456,70 +492,78 @@ t_stat lp09_detach (UNIT *uptr); /* LP09 LPT data structures - lp09_dev LPT device descriptor - lp09_unit LPT unit - lp09_reg LPT register list + 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 }; + 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 } }; + { 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 } }; + { 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 }; - + "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 dev, int32 pulse, int32 dat) { -int32 sb = pulse & 060; /* subopcode */ +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 ((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 (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 */ - } + 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; } @@ -529,29 +573,31 @@ 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 */ +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 */ +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; } @@ -569,7 +615,7 @@ 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 */ +lp09_err = (lp09_unit.flags & UNIT_ATT)? 0: 1; /* clr/set error */ return reason; } @@ -582,26 +628,26 @@ 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 */ +#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 */ +#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; @@ -623,77 +669,82 @@ int32 lp15_updsta (int32 new); /* LP15 LPT data structures - lp15_dev LPT device descriptor - lp15_unit LPT unit - lp15_reg LPT register list + 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 }; + 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 } }; + { 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 } }; + { 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 }; - + "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 dev, int32 pulse, int32 dat) { int32 header, sb; -sb = pulse & 060; /* subopcode */ +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 */ + 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 dev, 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 */ +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) @@ -701,64 +752,73 @@ 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 }; + 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); } +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; } } } +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 { /* packed */ + c[0] = (w0 >> 11) & 0177; + 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 */ +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 (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 */ +else CLR_INT (LPT); /* update int */ return lp15_sta; } @@ -766,11 +826,11 @@ return lp15_sta; 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 */ +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; } diff --git a/PDP18B/pdp18b_mt.c b/PDP18B/pdp18b_mt.c index dc5062be..d081f6ac 100644 --- a/PDP18B/pdp18b_mt.c +++ b/PDP18B/pdp18b_mt.c @@ -19,47 +19,48 @@ 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 + 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 + mt (PDP-9) TC59 magtape + (PDP-15) TC59D magtape - 18-Mar-05 RMS Added attached test to detach routine - 14-Jan-04 RMS Revised IO device call interface - 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 + 16-Aug-05 RMS Fixed C++ declaration and cast problems + 18-Mar-05 RMS Added attached test to detach routine + 14-Jan-04 RMS Revised IO device call interface + 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 + 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. @@ -68,69 +69,69 @@ #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) +#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)) +#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_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 */ -#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_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 */ +uint8 *mtxb = NULL; /* transfer buffer */ DEVICE mt_dev; int32 mt (int32 dev, int32 pulse, int32 dat); @@ -145,55 +146,59 @@ 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 + 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) } }; + { 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 } }; + { 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 } }; + { 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 }; - + "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 dev, int32 pulse, int32 dat) @@ -201,49 +206,52 @@ int32 mt (int32 dev, 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 */ +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 ((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); + 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 (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 */ + 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 @@ -257,123 +265,132 @@ 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 */ +u = (int32) (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->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); } +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 */ +switch (f) { /* case on function */ -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_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; + } + } /* end for */ + 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_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; + } + } /* end for */ + 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; -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_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_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 */ + 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 */ +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); + 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; + (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 */ + SET_INT (MTA); +else CLR_INT (MTA); /* int request */ return mt_sta; } @@ -384,10 +401,11 @@ 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; } +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; } @@ -396,38 +414,48 @@ return NULL; 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; } + + 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) @@ -436,14 +464,15 @@ 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)); +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 = (uint8 *) calloc (MT_MAXFR, sizeof (uint8)); if (mtxb == NULL) return SCPE_MEM; return SCPE_OK; } @@ -464,7 +493,7 @@ 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 */ +mt_updcsta (mt_dev.units + GET_UNIT (mt_cu), 0); /* update status */ return r; } @@ -472,8 +501,8 @@ return r; t_stat mt_detach (UNIT* uptr) { -if (!(uptr->flags & UNIT_ATT)) return SCPE_OK; /* attached? */ +if (!(uptr->flags & UNIT_ATT)) return SCPE_OK; /* attached? */ if (!sim_is_active (uptr)) uptr->USTAT = 0; -mt_updcsta (mt_dev.units + GET_UNIT (mt_cu), 0); /* update status */ +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 index bfd5f9e4..af0725a1 100644 --- a/PDP18B/pdp18b_rb.c +++ b/PDP18B/pdp18b_rb.c @@ -1,6 +1,6 @@ /* pdp18b_rb.c: RB09 fixed head disk simulator - Copyright (c) 2003-2004, Robert M Supnik + Copyright (c) 2003-2005, 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"), @@ -19,23 +19,23 @@ 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 + 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 + rb RB09 fixed head disk - 14-Jan-04 RMS Revised IO device call interface - 26-Oct-03 RMS Cleaned up buffer copy code + 14-Jan-04 RMS Revised IO device call interface + 26-Oct-03 RMS Cleaned up buffer copy code 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. + 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" @@ -43,51 +43,51 @@ /* 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 */ +#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 */ +#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 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)))) +#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 */ +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 dev, int32 pulse, int32 AC); @@ -98,44 +98,48 @@ 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 + 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) }; +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 } }; + { 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 } }; + { 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 }; - + "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 dev, int32 pulse, int32 AC) @@ -143,65 +147,70 @@ int32 rb71 (int32 dev, 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 (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 (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 */ + 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 */ +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 */ +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? */ +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 */ + 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; } +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; } @@ -209,14 +218,15 @@ 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; } +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) @@ -224,31 +234,35 @@ t_stat rb_svc (UNIT *uptr) int32 t, sw; int32 *fbuf = uptr->filebuf; -if ((uptr->flags & UNIT_BUF) == 0) { /* not buf? abort */ - rb_updsta (RBS_NRY | RBS_DON); /* set nxd, done */ - return IORETURN (rb_stopioe, SCPE_UNATT); } +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 { /* not locked */ - fbuf[rb_da] = M[rb_ma]; /* write word */ - 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] = fbuf[rb_da]; /* read word */ - 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 */ +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 { /* not locked */ + fbuf[rb_da] = M[rb_ma]; /* write word */ + 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] = fbuf[rb_da]; /* read word */ + 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 */ +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; } @@ -256,11 +270,11 @@ return SCPE_OK; 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 */ +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 */ + SET_INT (RB); /* set or clr intr */ else CLR_INT (RB); return rb_sta; } diff --git a/PDP18B/pdp18b_rf.c b/PDP18B/pdp18b_rf.c index f528c6b7..f84aaa35 100644 --- a/PDP18B/pdp18b_rf.c +++ b/PDP18B/pdp18b_rf.c @@ -1,6 +1,6 @@ /* pdp18b_rf.c: fixed head disk simulator - Copyright (c) 1993-2004, Robert M Supnik + Copyright (c) 1993-2005, 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"), @@ -19,102 +19,102 @@ 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 + 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 + rf (PDP-9) RF09/RF09 + (PDP-15) RF15/RS09 - 14-Jan-04 RMS Revised IO device call interface - Changed sim_fsize calling sequence - 26-Oct-03 RMS Cleaned up buffer copy code - 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 + 14-Jan-04 RMS Revised IO device call interface + Changed sim_fsize calling sequence + 26-Oct-03 RMS Cleaned up buffer copy code + 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. + 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) +#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 */ +#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_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)) -#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 */ +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 dev, int32 pulse, int32 dat); @@ -128,94 +128,102 @@ 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 + 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) }; +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 } }; + { 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 } }; + { 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 }; - + "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 dev, int32 pulse, int32 dat) { int32 t, sb; -sb = pulse & 060; /* subopcode */ +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 ((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 (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 */ + 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; } @@ -224,19 +232,21 @@ int32 rf72 (int32 dev, 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); } - } + 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) @@ -244,40 +254,46 @@ t_stat rf_svc (UNIT *uptr) int32 f, pa, d, t; int32 *fbuf = uptr->filebuf; -if ((uptr->flags & UNIT_BUF) == 0) { /* not buf? abort */ - rf_updsta (RFS_NED | RFS_DON); /* set nxd, done */ - return IORETURN (rf_stopioe, SCPE_UNATT); } +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] = fbuf[rf_da]; - if ((f == FN_WCHK) && (M[pa] != fbuf[rf_da])) { /* write check? */ - 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 { /* not locked */ - fbuf[rf_da] = M[pa]; /* write word */ - 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 */ +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] = fbuf[rf_da]; + if ((f == FN_WCHK) && (M[pa] != fbuf[rf_da])) { /* write check? */ + 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 { /* not locked */ + fbuf[rf_da] = M[pa]; /* write word */ + 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 */ +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) @@ -285,7 +301,7 @@ 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); + SET_INT (RF); else CLR_INT (RF); return rf_sta; } @@ -318,10 +334,11 @@ t_stat r; r = attach_unit (uptr, cptr); if (r != SCPE_OK) return r; if ((uptr->flags & UNIT_AUTO) && (sz = sim_fsize (uptr->fileref))) { - 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); } + 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 SCPE_OK; } diff --git a/PDP18B/pdp18b_rp.c b/PDP18B/pdp18b_rp.c index 2431dc39..cd9e8564 100644 --- a/PDP18B/pdp18b_rp.c +++ b/PDP18B/pdp18b_rp.c @@ -1,6 +1,6 @@ /* pdp18b_rp.c: RP15/RP02 disk pack simulator - Copyright (c) 1993-2004, Robert M Supnik + Copyright (c) 1993-2005, 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"), @@ -19,130 +19,130 @@ 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 + 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 + rp RP15/RP02 disk pack - 14-Jan-04 RMS Revised IO device call interface - 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 + 14-Jan-04 RMS Revised IO device call interface + 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_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 */ +#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 */ +#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_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) +#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_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 */ +#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 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 */ +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 dev, int32 pulse, int32 dat); @@ -156,93 +156,100 @@ 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 + 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) } }; + { 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 } }; + { 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 } }; + { 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 }; - + "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 dev, int32 pulse, int32 dat) { -int32 sb = pulse & 060; /* subopcode */ +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 ((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 (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 */ - } + 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 dev, int32 pulse, int32 dat) @@ -252,49 +259,52 @@ UNIT *uptr; sb = pulse & 060; if (pulse & 01) { - if (sb == 020) dat = IOT_SKP | dat; /* DPSN */ - } + 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 (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)); } } - } + 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 + 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 @@ -309,86 +319,100 @@ 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; } +u = (int32) (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) || (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 (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 ((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 ((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; } +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 */ +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_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_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); } +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 */ +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 */ +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 */ +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); } +if (err != 0) { /* error? */ + perror ("RP I/O error"); + clearerr (uptr->fileref); + return IORETURN (rp_stopioe, SCPE_IOERR); + } return SCPE_OK; } @@ -405,9 +429,10 @@ 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; } + 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)) || @@ -415,7 +440,7 @@ if (((rp_sta & (STA_ERR | STA_DON)) && (rp_sta & STA_IED)) || else CLR_INT (RP); return; } - + /* Reset routine */ t_stat rp_reset (DEVICE *dptr) @@ -426,9 +451,10 @@ 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; } + uptr = rp_dev.units + i; + sim_cancel (uptr); + uptr->CYL = uptr->FUNC = 0; + } return SCPE_OK; } diff --git a/PDP18B/pdp18b_stddev.c b/PDP18B/pdp18b_stddev.c index 02b4e941..098c4831 100644 --- a/PDP18B/pdp18b_stddev.c +++ b/PDP18B/pdp18b_stddev.c @@ -1,6 +1,6 @@ /* pdp18b_stddev.c: 18b PDP's standard devices - Copyright (c) 1993-2004, Robert M Supnik + Copyright (c) 1993-2005, 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"), @@ -19,54 +19,54 @@ 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 + 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 + ptr paper tape reader + ptp paper tape punch + tti keyboard + tto teleprinter + clk clock - 28-May-04 RMS Removed SET TTI CTRL-C - 16-Feb-04 RMS Fixed bug in hardware read-in mode bootstrap - 14-Jan-04 RMS Revised IO device call interface - CAF does not turn off the clock - 29-Dec-03 RMS Added console backpressure support - 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, SET TTI CTRL-C - 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 + 28-May-04 RMS Removed SET TTI CTRL-C + 16-Feb-04 RMS Fixed bug in hardware read-in mode bootstrap + 14-Jan-04 RMS Revised IO device call interface + CAF does not turn off the clock + 29-Dec-03 RMS Added console backpressure support + 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, SET TTI CTRL-C + 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) +#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; @@ -79,8 +79,8 @@ 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 clk_tps = 60; /* ticks/second */ +int32 tmxr_poll = 16000; /* term mux poll */ int32 ptr (int32 dev, int32 pulse, int32 dat); int32 ptp (int32 dev, int32 pulse, int32 dat); @@ -114,9 +114,9 @@ extern int32 upd_iors (void); /* CLK data structures - clk_dev CLK device descriptor - clk_unit CLK unit - clk_reg CLK register list + clk_dev CLK device descriptor + clk_unit CLK unit + clk_reg CLK register list */ DIB clk_dib = { 0, 0, &clk_iors, { NULL } }; @@ -124,147 +124,159 @@ 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 } }; + { 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 } }; + { 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 }; - + "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 + 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 }; + 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) }, + { 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) }, + { 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 } }; + { 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 } }; + { 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 }; + "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 + 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 }; + UDATA (&ptp_svc, UNIT_SEQ+UNIT_ATTABLE, 0), SERIAL_OUT_WAIT + }; 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) }, + { 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) }, + { 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 } }; + { 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 } }; + { 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 }; - + "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 + 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 +#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 */ + 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 +#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) +#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 } }; @@ -275,107 +287,117 @@ 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) }, + { 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 }, + { 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 } }; + { 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 }, + { 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 }, #endif - { MTAB_XTD|MTAB_VDV, 0, "DEVNO", NULL, NULL, &show_devno, NULL }, - { 0 } }; + { 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 }; - + "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 + 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) +#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 }; + 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 +#define TTO_WIDTH 8 #endif -#define TTO_MASK ((1 << TTO_WIDTH) - 1) +#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) }, + { 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 }, + { 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 } }; + { 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 }, + { 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 } }; + { 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 }; - + "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 dev, 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 */ +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; } @@ -385,12 +407,13 @@ 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 */ +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; } @@ -405,11 +428,12 @@ return (TST_INT (CLK)? IOS_CLK: 0); t_stat clk_reset (DEVICE *dptr) { -CLR_INT (CLK); /* clear flag */ -tmxr_poll = clk_unit.wait; /* set mux poll */ -if (!sim_is_running) { /* RESET? */ - clk_state = 0; /* clock off */ - sim_cancel (&clk_unit); } /* stop clock */ +CLR_INT (CLK); /* clear flag */ +tmxr_poll = clk_unit.wait; /* set mux poll */ +if (!sim_is_running) { /* RESET? */ + clk_state = 0; /* clock off */ + sim_cancel (&clk_unit); /* stop clock */ + } return SCPE_OK; } @@ -430,21 +454,24 @@ 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 dev, 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); } +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; } @@ -454,35 +481,41 @@ t_stat ptr_svc (UNIT *uptr) { int32 temp; -if ((ptr_unit.flags & UNIT_ATT) == 0) { /* attached? */ +if ((ptr_unit.flags & UNIT_ATT) == 0) { /* attached? */ #if defined (IOS_PTRERR) - SET_INT (PTR); /* if err, set int */ - ptr_err = 1; + 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? */ + 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; + 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 */ + 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; } @@ -491,11 +524,11 @@ return SCPE_OK; t_stat ptr_reset (DEVICE *dptr) { -ptr_state = 0; /* clear state */ +ptr_state = 0; /* clear state */ ptr_unit.buf = 0; -CLR_INT (PTR); /* clear flag */ +CLR_INT (PTR); /* clear flag */ ptr_err = (ptr_unit.flags & UNIT_ATT)? 0: 1; -sim_cancel (&ptr_unit); /* deactivate unit */ +sim_cancel (&ptr_unit); /* deactivate unit */ return SCPE_OK; } @@ -505,11 +538,11 @@ int32 ptr_iors (void) { return ((TST_INT (PTR)? IOS_PTR: 0) #if defined (IOS_PTRERR) - | (ptr_err? IOS_PTRERR: 0) + | (ptr_err? IOS_PTRERR: 0) #endif - ); + ); } - + /* Attach routine */ t_stat ptr_attach (UNIT *uptr, char *cptr) @@ -520,7 +553,7 @@ 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; + ptr_unit.flags = ptr_unit.flags | UNIT_RASCII; return reason; } @@ -540,13 +573,15 @@ int32 ptr_getw (UNIT *uptr, int32 *hi) int32 word, bits, st, ch; word = st = bits = 0; -do { if ((ch = getc (uptr->fileref)) == EOF) return -1; - uptr->pos = uptr->pos + 1; - if (ch & 0200) { - word = (word << 6) | (ch & 077); - bits = (bits << 1) | ((ch >> 6) & 1); - st++; } } -while (st < 3); +do { + if ((ch = getc (uptr->fileref)) == EOF) return -1; + uptr->pos = uptr->pos + 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; } @@ -555,15 +590,18 @@ t_stat ptr_rim_load (UNIT *uptr, int32 origin) { int32 bits, val; -for (;;) { /* word loop */ - if ((val = ptr_getw (uptr, &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; } +for (;;) { /* word loop */ + if ((val = ptr_getw (uptr, &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; } @@ -576,141 +614,141 @@ return SCPE_FMT; 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_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 */ -}; + 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) { @@ -718,16 +756,17 @@ 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, ASW); +if (sim_switches & SWMASK ('H')) /* hardware RIM load? */ + return ptr_rim_load (&ptr_unit, ASW); #endif -if (ptr_dib.dev != DEV_PTR) return STOP_NONSTD; /* non-std addr? */ -if (MEMSIZE < 8192) mask = 0767777; /* 4k? */ +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; } + 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; } @@ -742,19 +781,21 @@ return ptr_rim_load (&ptr_unit, ASW); } #endif - + /* Paper tape punch: IOT routine */ int32 ptp (int32 dev, 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 */ +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; } @@ -762,19 +803,22 @@ return dat; 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; } +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; } @@ -783,21 +827,21 @@ return SCPE_OK; int32 ptp_iors (void) { -return ((TST_INT (PTP)? IOS_PTP: 0) +return ((TST_INT (PTP)? IOS_PTP: 0) #if defined (IOS_PTPERR) - | (ptp_err? IOS_PTPERR: 0) + | (ptp_err? IOS_PTPERR: 0) #endif - ); + ); } - + /* Reset routine */ t_stat ptp_reset (DEVICE *dptr) { ptp_unit.buf = 0; -CLR_INT (PTP); /* clear flag */ +CLR_INT (PTP); /* clear flag */ ptp_err = (ptp_unit.flags & UNIT_ATT)? 0: 1; -sim_cancel (&ptp_unit); /* deactivate unit */ +sim_cancel (&ptp_unit); /* deactivate unit */ return SCPE_OK; } @@ -811,7 +855,7 @@ 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; + ptp_unit.flags = ptp_unit.flags | UNIT_PASCII; return reason; } @@ -823,18 +867,21 @@ ptp_err = 1; ptp_unit.flags = ptp_unit.flags & ~UNIT_PASCII; return detach_unit (uptr); } - + /* Terminal input: IOT routine */ int32 tti (int32 dev, 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 (); } +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; } @@ -842,44 +889,50 @@ return dat; t_stat tti_svc (UNIT *uptr) { -#if defined (KSR28) /* Baudot... */ +#if defined (KSR28) /* Baudot... */ int32 c; -sim_activate (uptr, uptr->wait); /* continue poll */ -if (tti_state & TTI_2ND) { /* char waiting? */ - uptr->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)) uptr->buf = c & TTI_MASK; - else { - uptr->buf = (c & TTI_FIGURES)? - BAUDOT_FIGURES: BAUDOT_LETTERS; - tti_state = c | TTI_2ND; } } /* set 2nd waiting */ +sim_activate (uptr, uptr->wait); /* continue poll */ +if (tti_state & TTI_2ND) { /* char waiting? */ + uptr->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)) uptr->buf = c & TTI_MASK; + else { + uptr->buf = (c & TTI_FIGURES)? + BAUDOT_FIGURES: BAUDOT_LETTERS; + tti_state = c | TTI_2ND; /* set 2nd waiting */ + } + } -#else /* ASCII... */ +#else /* ASCII... */ int32 c, out; -sim_activate (uptr, uptr->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 (uptr->flags & UNIT_KSR) { /* KSR? */ - if (islower (out)) out = toupper (out); /* convert to UC */ - c = out | 0200; } /* set TTY bit */ -else c = c & ((uptr->flags & UNIT_8B)? 0377: 0177); /* no, 7b/8b */ -if ((uptr->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; } -uptr->buf = c; /* got char */ +sim_activate (uptr, uptr->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 (uptr->flags & UNIT_KSR) { /* KSR? */ + if (islower (out)) out = toupper (out); /* convert to UC */ + c = out | 0200; /* set TTY bit */ + } +else c = c & ((uptr->flags & UNIT_8B)? 0377: 0177); /* no, 7b/8b */ +if ((uptr->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; + } +uptr->buf = c; /* got char */ #endif uptr->pos = uptr->pos + 1; -SET_INT (TTI); /* set flag */ +SET_INT (TTI); /* set flag */ return SCPE_OK; } @@ -894,34 +947,25 @@ return (TST_INT (TTI)? IOS_TTI: 0); 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 */ +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 dev, 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 */ +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; } @@ -932,26 +976,29 @@ t_stat tto_svc (UNIT *uptr) int32 c; t_stat r; -#if defined (KSR28) /* Baudot... */ -if (uptr->buf == BAUDOT_FIGURES) /* set figures? */ - tto_state = TTO_FIGURES; -else if (uptr->buf == BAUDOT_LETTERS) /* set letters? */ - tto_state = 0; -else { c = tto_trans[uptr->buf + tto_state]; /* translate */ +#if defined (KSR28) /* Baudot... */ +if (uptr->buf == BAUDOT_FIGURES) /* set figures? */ + tto_state = TTO_FIGURES; +else if (uptr->buf == BAUDOT_LETTERS) /* set letters? */ + tto_state = 0; +else { + c = tto_trans[uptr->buf + tto_state]; /* translate */ #else -c = uptr->buf & 0177; /* assume 7b or KSR */ -if (!(uptr->flags & UNIT_KSR) || /* 7b/8b or */ - ((c >= 007) && (c <= 0137))) { /* in range? */ - if ((uptr->flags & UNIT_KSR) && islower (c)) /* KSR? */ - c = toupper (c); - else if (tto_unit.flags & UNIT_8B) c = uptr->buf; +c = uptr->buf & 0177; /* assume 7b or KSR */ +if (!(uptr->flags & UNIT_KSR) || /* 7b/8b or */ + ((c >= 007) && (c <= 0137))) { /* in range? */ + if ((uptr->flags & UNIT_KSR) && islower (c)) /* KSR? */ + c = toupper (c); + else if (tto_unit.flags & UNIT_8B) c = uptr->buf; #endif - if ((r = sim_putchar_s (c)) != SCPE_OK) { /* output; error? */ - sim_activate (uptr, uptr->wait); /* retry? */ - return ((r == SCPE_STALL)? SCPE_OK: r); } } -SET_INT (TTO); /* set flag */ + if ((r = sim_putchar_s (c)) != SCPE_OK) { /* output; error? */ + sim_activate (uptr, uptr->wait); /* retry? */ + return ((r == SCPE_STALL)? SCPE_OK: r); + } + } +SET_INT (TTO); /* set flag */ uptr->pos = uptr->pos + 1; return SCPE_OK; } @@ -967,10 +1014,10 @@ return (TST_INT (TTO)? IOS_TTO: 0); 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 */ +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; } diff --git a/PDP18B/pdp18b_sys.c b/PDP18B/pdp18b_sys.c index fd3007de..ee6037c3 100644 --- a/PDP18B/pdp18b_sys.c +++ b/PDP18B/pdp18b_sys.c @@ -1,6 +1,6 @@ /* pdp18b_sys.c: 18b PDP's simulator interface - Copyright (c) 1993-2004, Robert M Supnik + Copyright (c) 1993-2005, 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"), @@ -19,32 +19,33 @@ 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 + 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-04 RMS Fixed instruction table errors - 18-Oct-03 RMS Added DECtape off reel message - 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) + 22-Jul-05 RMS Removed AAS, error in V1 reference manual + 09-Jan-04 RMS Fixed instruction table errors + 18-Oct-03 RMS Added DECtape off reel message + 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" @@ -98,12 +99,12 @@ 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 + 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) @@ -121,60 +122,62 @@ REG *sim_PC = &cpu_reg[0]; int32 sim_emax = 2; DEVICE *sim_devices[] = { - &cpu_dev, + &cpu_dev, #if defined (PDP15) - &fpp_dev, + &fpp_dev, #endif - &ptr_dev, - &ptp_dev, - &tti_dev, - &tto_dev, - &clk_dev, + &ptr_dev, + &ptp_dev, + &tti_dev, + &tto_dev, + &clk_dev, #if defined (TYPE62) - &lp62_dev, + &lp62_dev, #endif #if defined (TYPE647) - &lp647_dev, + &lp647_dev, #endif #if defined (LP09) - &lp09_dev, + &lp09_dev, #endif #if defined (LP15) - &lp15_dev, + &lp15_dev, #endif #if defined (DRM) - &drm_dev, + &drm_dev, #endif #if defined (RB) - &rb_dev, + &rb_dev, #endif #if defined (RF) - &rf_dev, + &rf_dev, #endif #if defined (RP) - &rp_dev, + &rp_dev, #endif - &dt_dev, + &dt_dev, #if defined (MTA) - &mt_dev, + &mt_dev, #endif #if defined (TTY1) - &tti1_dev, &tto1_dev, + &tti1_dev, &tto1_dev, #endif - NULL }; + 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", - "DECtape off reel" }; - + "Unknown error", + "Undefined instruction", + "HALT instruction", + "Breakpoint", + "Nested XCT's", + "Invalid API interrupt", + "Non-standard device number", + "Memory management error", + "FP15 instruction disabled", + "DECtape off reel" + }; + /* Binary loaders */ int32 getword (FILE *fileref, int32 *hi) @@ -182,12 +185,14 @@ 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); +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; } @@ -195,12 +200,12 @@ return word; /* PDP-4/PDP-7 RIM format loader Tape format - dac addr - data - : - dac addr - data - jmp addr or hlt + dac addr + data + : + dac addr + data + jmp addr or hlt */ t_stat rim_load_47 (FILE *fileref, char *cptr) @@ -210,26 +215,29 @@ 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 */ + 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) break; /* HLT? */ + else return SCPE_FMT; /* error */ + } +return SCPE_OK; /* done */ } /* PDP-9/15 RIM format loader Tape format (read in address specified externally) - data - : - data - word to execute (bit 1 of last character set) + data + : + data + word to execute (bit 1 of last character set) */ t_stat rim_load_915 (FILE *fileref, char *cptr) @@ -238,62 +246,69 @@ 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 */ +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; } +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) + 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; } +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; } @@ -316,99 +331,100 @@ 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? */ +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 */ + 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 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 }; + 0777777, 0777777 + }; /* If both NPN (clear AC) and NPI versions of an IOT are defined, the NPN version must come first */ static const char *opcode[] = { - "CAL", "DAC", "JMS", "DZM", /* mem refs */ + "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 */ +#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 */ + "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 */ + "LAW", /* LAW */ - "LACQ", "LACS", "ABS", "GSM", "LMQ", /* EAE */ + "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 */ + "EAE-setup", "EAE", /* setup, general */ - "CLSF", "IOF", "ION", "CLOF", "CLON", /* standard IO devs */ + "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 */ +#if defined (TYPE62) /* Type 62 */ "LPSF", "LPCF", "LPLD", "LPSE", "LSSF", "LSCF", "LSPR", #endif -#if defined (TYPE647) /* Type 647 */ +#if defined (TYPE647) /* Type 647 */ "LPSF", "LPCB", "LPCD", "LPCD", "LPCD", "LPL2", "LPLD", "LPL1", "LPEF", "LPCF", "LPCF", "LPCF", "LPCF", @@ -418,22 +434,22 @@ static const char *opcode[] = { "LSDF", "LSEF", "LSCF", "LPLD", "LIOF", "LION", #endif -#if defined (LP15) /* LP15 */ +#if defined (LP15) /* LP15 */ "LPSF", "LPPM", "LPP1", "LPDI", "LPRS", "LPOS", "LPEI", "LPCD", "LPCF", #endif -#if defined (DRM) /* drum */ +#if defined (DRM) /* drum */ "DRLR", "DRLW", "DRSS", "DRCS", "DRSF", "DRSN", "DRCF", "DRLCRD", "DRLCWR", "DRLBLK", "DRCONT", "DRSF", "DRSOK", "DRCF", #endif -#if defined (RB) /* RB09 */ +#if defined (RB) /* RB09 */ "DBCF", "DBRD", "DBLD", "DBSF", "DBRS", "DBLW", "DBCS", "DBLM", "DBLS", #endif -#if defined (RF) /* RF09 */ +#if defined (RF) /* RF09 */ "DSSF", "DSCC", "DSCF", "DRBR", "DRAL", "DSFX", "DRAH", "DLBR", "DLAL", "DSCN", "DLAH", @@ -450,14 +466,14 @@ static const char *opcode[] = { "DPRC", "DPOC", "DPRW", "DPOW", "DPCF", "DPLZ", "DPCN", "DPLO", "DPLF", #endif -#if defined (MTA) /* TC59 */ +#if defined (MTA) /* TC59 */ "MTTR", "MTCR", "MTSF", "MTRC", "MTAF", "MTRS", "MTGO", "MTCM", "MTLC", #endif -#if defined (TYPE550) /* Type 550 */ +#if defined (TYPE550) /* Type 550 */ "MMDF", "MMEF", "MMRD", "MMWR", "MMBF", "MMRS", "MMLC", "MMSE", -#elif defined (TC02) /* TC02/TC15 */ +#elif defined (TC02) /* TC02/TC15 */ "DTCA", "DTRA", "DTXA", "DTLA", "DTEF", "DTRB", "DTDF", #endif @@ -478,12 +494,12 @@ static const char *opcode[] = { "SBA", "DBA", "EBA", "RDMM", "ORMM", "LDMM", "MPLR", "ENB", "INH", "MPRC", "IPFH", - "AAS", "PAX", "PAL", "AAC", - "PXA", "AXS", "PXL", "PLA", - "PLX", "CLAC","CLX", "CLLR", "AXR", + "PAX", "PAL", "AAC", "PXA", + "AXS", "PXL", "PLA", "PLX", + "CLAC","CLX", "CLLR", "AXR", - "FPT", /* FP15 */ - "ISB", "ESB", /* mem ref */ + "FPT", /* FP15 */ + "ISB", "ESB", /* mem ref */ "FSB", "URFSB", "UNFSB", "UUFSB", "DSB", "URDSB", "UNDSB", "UUDSB", "IRS", "ERS", @@ -513,7 +529,7 @@ static const char *opcode[] = { "DAD", "URDAD", "UNDAD", "UUDAD", "BZA", "BMA", "BLE", "BPA", "BRU", "BNA", "BAC", - "ISB*", "ESB*", /* indirect */ + "ISB*", "ESB*", /* indirect */ "FSB*", "URFSB*", "UNFSB*", "UUFSB*", "DSB*", "URDSB*", "UNDSB*", "UUDSB*", "IRS*", "ERS*", @@ -542,7 +558,7 @@ static const char *opcode[] = { "FAD*", "URFAD*", "UNFAD*", "UUFAD*", "DAD*", "URDAD*", "UNDAD*", "UUDAD*", - "FLA", "UNFLA", "FXA", "URFXA", /* no operand */ + "FLA", "UNFLA", "FXA", "URFXA", /* no operand */ "SWQ", "UNSWQ", "FZR", "FAB", "FNG", "FCM", "FNM", #endif @@ -552,7 +568,7 @@ static const char *opcode[] = { "TTS", "CAF", "DBK", "DBR", "SPI", "RPL", "ISA", #endif - "IOT", /* general */ + "IOT", /* general */ "NOP", "STL", "RCL", "RCR", "CLC", "LAS", "GLK", @@ -603,11 +619,12 @@ static const char *opcode[] = { "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 */ + "LLK", "CLQ", "LSN", "OACQ", "ECLA", /* encode only masks */ "CMQ", "OMQ", "OSC", "CLA", "CLL", "CML", "CMA", "OAS", "HLT", - NULL }; + NULL + }; static const int32 opc_val[] = { 0000000+I_MRF, 0040000+I_MRF, 0100000+I_MRF, 0140000+I_MRF, @@ -685,10 +702,10 @@ static const int32 opc_val[] = { 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 */ +#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 */ +#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 @@ -709,9 +726,9 @@ static const int32 opc_val[] = { 0707761+I_NPI, 0707762+I_NPI, 0707764+I_NPI, 0700032+I_NPN, 0700022+I_NPI, 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, + 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, @@ -744,7 +761,7 @@ static const int32 opc_val[] = { 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 */ + 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, @@ -823,180 +840,204 @@ static const int32 opc_val[] = { 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 }; - + -1 + }; + /* Operate or EAE decode Inputs: - *of = output stream - inst = mask bits - class = instruction class code - sp = space needed? + *of = output stream + inst = mask bits + class = instruction class code + sp = space needed? Outputs: - status = space needed? + 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; } } +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 + *of = output stream + addr = current PC + *val = pointer to values + *uptr = pointer to unit + sw = switches Outputs: - return = status code + 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) + 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 (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; } +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? */ +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 */ + 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"); + 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)); + 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 */ + 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 + *cptr = pointer to input string + *sign = pointer to sign + *status = pointer to error status Outputs: - val = output value + val = output value */ t_value get_sint (char *cptr, int32 *sign, t_stat *status) { *sign = 0; if (*cptr == '+') { - *sign = 1; - cptr++; } + *sign = 1; + cptr++; + } else if (*cptr == '-') { - *sign = -1; - 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 + *cptr = pointer to input string + addr = current PC + uptr = pointer to unit + *val = pointer to output values + sw = switches Outputs: - status = error status + status = error status */ t_stat parse_sym (char *cptr, t_addr addr, UNIT *uptr, t_value *val, int32 sw) @@ -1008,118 +1049,136 @@ 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 (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 (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 (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; } + 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 */ +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 */ +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 */ +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 */ + 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 */ + 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); } + 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; + 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; } } + 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? */ + 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 index 4da1c99d..8a85a56d 100644 --- a/PDP18B/pdp18b_tt1.c +++ b/PDP18B/pdp18b_tt1.c @@ -1,6 +1,6 @@ /* pdp15_ttx.c: PDP-15 additional terminals simulator - Copyright (c) 1993-2004, Robert M Supnik + Copyright (c) 1993-2005, 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"), @@ -19,13 +19,15 @@ 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 + 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 LT15/LT19 terminal input/output + ttix,ttox LT15/LT19 terminal input/output - 14-Jan-04 RMS Cloned from pdp8_ttx.c + 29-Jun-05 RMS Added SET TTOXn DISCONNECT + 21-Jun-05 RMS Fixed bug in SHOW CONN/STATS + 14-Jan-04 RMS Cloned from pdp8_ttx.c This module implements 16 individual serial interfaces similar in function to the console. These interfaces are mapped to Telnet based connections as @@ -39,25 +41,25 @@ #include #if defined (PDP15) -#define TTX_MAXL 16 /* max number of lines */ +#define TTX_MAXL 16 /* max number of lines */ #elif defined (PDP9) -#define TTX_MAXL 4 +#define TTX_MAXL 4 #else -#define TTX_MAXL 1 +#define TTX_MAXL 1 #endif -#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) +#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 ttix_done = 0; /* input flags */ -uint32 ttox_done = 0; /* output flags */ -uint8 ttix_buf[TTX_MAXL] = { 0 }; /* input buffers */ -uint8 ttox_buf[TTX_MAXL] = { 0 }; /* output buffers */ -TMLN ttx_ldsc[TTX_MAXL] = { 0 }; /* line descriptors */ -TMXR ttx_desc = { 1, 0, 0, ttx_ldsc }; /* mux descriptor */ -#define ttx_lines ttx_desc.lines /* current number of lines */ +uint32 ttix_done = 0; /* input flags */ +uint32 ttox_done = 0; /* output flags */ +uint8 ttix_buf[TTX_MAXL] = { 0 }; /* input buffers */ +uint8 ttox_buf[TTX_MAXL] = { 0 }; /* output buffers */ +TMLN ttx_ldsc[TTX_MAXL] = { 0 }; /* line descriptors */ +TMXR ttx_desc = { 1, 0, 0, ttx_ldsc }; /* mux descriptor */ +#define ttx_lines ttx_desc.lines /* current number of lines */ extern int32 int_hwre[API_HLVL+1]; extern int32 tmxr_poll; @@ -82,113 +84,126 @@ void ttx_reset_ln (int32 i); t_stat ttx_summ (FILE *st, UNIT *uptr, int32 val, void *desc); t_stat ttx_show (FILE *st, UNIT *uptr, int32 val, void *desc); t_stat ttx_vlines (UNIT *uptr, int32 val, char *cptr, void *desc); - + /* TTIx data structures - ttix_dev TTIx device descriptor - ttix_unit TTIx unit descriptor - ttix_reg TTIx register list - ttix_mod TTIx modifiers list + ttix_dev TTIx device descriptor + ttix_unit TTIx unit descriptor + ttix_reg TTIx register list + ttix_mod TTIx modifiers list */ -DIB ttix_dib = { DEV_TTO1, 8, NULL, - { &ttox, &ttix, &ttox, &ttix, &ttox, &ttix, &ttox, &ttix } }; +DIB ttix_dib = { + DEV_TTO1, 8, NULL, + { &ttox, &ttix, &ttox, &ttix, &ttox, &ttix, &ttox, &ttix } + }; UNIT ttix_unit = { UDATA (&ttix_svc, UNIT_ATTABLE, 0), KBD_POLL_WAIT }; REG ttx_nlreg = { DRDATA (NLINES, ttx_lines, 4), PV_LEFT }; REG ttix_reg[] = { - { BRDATA (BUF, ttix_buf, 8, 8, TTX_MAXL) }, - { ORDATA (DONE, ttix_done, TTX_MAXL) }, - { FLDATA (INT, int_hwre[API_TTI1], INT_V_TTI1) }, - { DRDATA (TIME, ttix_unit.wait, 24), REG_NZ + PV_LEFT }, - { ORDATA (DEVNUM, ttix_dib.dev, 6), REG_HRO }, - { NULL } }; + { BRDATA (BUF, ttix_buf, 8, 8, TTX_MAXL) }, + { ORDATA (DONE, ttix_done, TTX_MAXL) }, + { FLDATA (INT, int_hwre[API_TTI1], INT_V_TTI1) }, + { DRDATA (TIME, ttix_unit.wait, 24), REG_NZ + PV_LEFT }, + { ORDATA (DEVNUM, ttix_dib.dev, 6), REG_HRO }, + { NULL } + }; MTAB ttix_mod[] = { - { MTAB_XTD | MTAB_VDV | MTAB_VAL, 0, "lines", "LINES", - &ttx_vlines, NULL, &ttx_nlreg }, - { 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_devno, &show_devno, NULL }, - { MTAB_XTD|MTAB_VUN|MTAB_NC, 0, "LOG", "LOG", - &tmxr_set_log, &tmxr_show_log, &ttx_desc }, - { MTAB_XTD|MTAB_VUN|MTAB_NC, 0, NULL, "NOLOG", - &tmxr_set_nolog, NULL, &ttx_desc }, - { 0 } }; + { MTAB_XTD | MTAB_VDV | MTAB_VAL, 0, "lines", "LINES", + &ttx_vlines, NULL, &ttx_nlreg }, + { 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_devno, &show_devno, NULL }, + { 0 } + }; DEVICE tti1_dev = { - "TTIX", &ttix_unit, ttix_reg, ttix_mod, - 1, 10, 31, 1, 8, 8, - &tmxr_ex, &tmxr_dep, &ttx_reset, - NULL, &ttx_attach, &ttx_detach, - &ttix_dib, DEV_NET | DEV_DISABLE }; + "TTIX", &ttix_unit, ttix_reg, ttix_mod, + 1, 10, 31, 1, 8, 8, + &tmxr_ex, &tmxr_dep, &ttx_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 + ttox_dev TTOx device descriptor + ttox_unit TTOx unit descriptor + ttox_reg TTOx register list */ UNIT ttox_unit[] = { - { UDATA (&ttox_svc, UNIT_KSR, 0), SERIAL_OUT_WAIT }, - { UDATA (&ttox_svc, UNIT_KSR+UNIT_DIS, 0), SERIAL_OUT_WAIT }, - { UDATA (&ttox_svc, UNIT_KSR+UNIT_DIS, 0), SERIAL_OUT_WAIT }, - { UDATA (&ttox_svc, UNIT_KSR+UNIT_DIS, 0), SERIAL_OUT_WAIT }, - { UDATA (&ttox_svc, UNIT_KSR+UNIT_DIS, 0), SERIAL_OUT_WAIT }, - { UDATA (&ttox_svc, UNIT_KSR+UNIT_DIS, 0), SERIAL_OUT_WAIT }, - { UDATA (&ttox_svc, UNIT_KSR+UNIT_DIS, 0), SERIAL_OUT_WAIT }, - { UDATA (&ttox_svc, UNIT_KSR+UNIT_DIS, 0), SERIAL_OUT_WAIT }, - { UDATA (&ttox_svc, UNIT_KSR+UNIT_DIS, 0), SERIAL_OUT_WAIT }, - { UDATA (&ttox_svc, UNIT_KSR+UNIT_DIS, 0), SERIAL_OUT_WAIT }, - { UDATA (&ttox_svc, UNIT_KSR+UNIT_DIS, 0), SERIAL_OUT_WAIT }, - { UDATA (&ttox_svc, UNIT_KSR+UNIT_DIS, 0), SERIAL_OUT_WAIT }, - { UDATA (&ttox_svc, UNIT_KSR+UNIT_DIS, 0), SERIAL_OUT_WAIT }, - { UDATA (&ttox_svc, UNIT_KSR+UNIT_DIS, 0), SERIAL_OUT_WAIT }, - { UDATA (&ttox_svc, UNIT_KSR+UNIT_DIS, 0), SERIAL_OUT_WAIT }, - { UDATA (&ttox_svc, UNIT_KSR+UNIT_DIS, 0), SERIAL_OUT_WAIT } }; + { UDATA (&ttox_svc, UNIT_KSR, 0), SERIAL_OUT_WAIT }, + { UDATA (&ttox_svc, UNIT_KSR+UNIT_DIS, 0), SERIAL_OUT_WAIT }, + { UDATA (&ttox_svc, UNIT_KSR+UNIT_DIS, 0), SERIAL_OUT_WAIT }, + { UDATA (&ttox_svc, UNIT_KSR+UNIT_DIS, 0), SERIAL_OUT_WAIT }, + { UDATA (&ttox_svc, UNIT_KSR+UNIT_DIS, 0), SERIAL_OUT_WAIT }, + { UDATA (&ttox_svc, UNIT_KSR+UNIT_DIS, 0), SERIAL_OUT_WAIT }, + { UDATA (&ttox_svc, UNIT_KSR+UNIT_DIS, 0), SERIAL_OUT_WAIT }, + { UDATA (&ttox_svc, UNIT_KSR+UNIT_DIS, 0), SERIAL_OUT_WAIT }, + { UDATA (&ttox_svc, UNIT_KSR+UNIT_DIS, 0), SERIAL_OUT_WAIT }, + { UDATA (&ttox_svc, UNIT_KSR+UNIT_DIS, 0), SERIAL_OUT_WAIT }, + { UDATA (&ttox_svc, UNIT_KSR+UNIT_DIS, 0), SERIAL_OUT_WAIT }, + { UDATA (&ttox_svc, UNIT_KSR+UNIT_DIS, 0), SERIAL_OUT_WAIT }, + { UDATA (&ttox_svc, UNIT_KSR+UNIT_DIS, 0), SERIAL_OUT_WAIT }, + { UDATA (&ttox_svc, UNIT_KSR+UNIT_DIS, 0), SERIAL_OUT_WAIT }, + { UDATA (&ttox_svc, UNIT_KSR+UNIT_DIS, 0), SERIAL_OUT_WAIT }, + { UDATA (&ttox_svc, UNIT_KSR+UNIT_DIS, 0), SERIAL_OUT_WAIT } + }; REG ttox_reg[] = { - { BRDATA (BUF, ttox_buf, 8, 8, TTX_MAXL) }, - { ORDATA (DONE, ttox_done, TTX_MAXL) }, - { FLDATA (INT, int_hwre[API_TTO1], INT_V_TTO1) }, - { URDATA (TIME, ttox_unit[0].wait, 10, 24, 0, - TTX_MAXL, PV_LEFT) }, - { NULL } }; + { BRDATA (BUF, ttox_buf, 8, 8, TTX_MAXL) }, + { ORDATA (DONE, ttox_done, TTX_MAXL) }, + { FLDATA (INT, int_hwre[API_TTO1], INT_V_TTO1) }, + { URDATA (TIME, ttox_unit[0].wait, 10, 24, 0, + TTX_MAXL, PV_LEFT) }, + { NULL } + }; MTAB ttox_mod[] = { - { UNIT_KSR+UNIT_8B, UNIT_KSR, "KSR", "KSR", NULL }, - { UNIT_KSR+UNIT_8B, 0 , "7b" , "7B" , NULL }, - { UNIT_KSR+UNIT_8B, UNIT_8B , "8b" , "8B" , NULL }, - { 0 } }; + { UNIT_KSR+UNIT_8B, UNIT_KSR, "KSR", "KSR", NULL }, + { UNIT_KSR+UNIT_8B, 0 , "7b" , "7B" , NULL }, + { UNIT_KSR+UNIT_8B, UNIT_8B , "8b" , "8B" , NULL }, + { MTAB_XTD|MTAB_VUN, 0, NULL, "DISCONNECT", + &tmxr_dscln, NULL, &ttx_desc }, + { MTAB_XTD|MTAB_VUN|MTAB_NC, 0, "LOG", "LOG", + &tmxr_set_log, &tmxr_show_log, &ttx_desc }, + { MTAB_XTD|MTAB_VUN|MTAB_NC, 0, NULL, "NOLOG", + &tmxr_set_nolog, NULL, &ttx_desc }, + { 0 } + }; DEVICE tto1_dev = { - "TTOX", ttox_unit, ttox_reg, ttox_mod, - TTX_MAXL, 10, 31, 1, 8, 8, - NULL, NULL, &ttx_reset, - NULL, NULL, NULL, - NULL, DEV_DISABLE }; - + "TTOX", ttox_unit, ttox_reg, ttox_mod, + TTX_MAXL, 10, 31, 1, 8, 8, + NULL, NULL, &ttx_reset, + NULL, NULL, NULL, + NULL, DEV_DISABLE + }; + /* Terminal input: IOT routine */ int32 ttix (int32 dev, int32 pulse, int32 dat) { -int32 ln = ttx_getln (dev, pulse); /* line # */ +int32 ln = ttx_getln (dev, pulse); /* line # */ if (ln > ttx_lines) return dat; -if (pulse & 001) { /* KSF1 */ - if (ttix_test_done (ln)) dat = dat | IOT_SKP; } -if (pulse & 002) { /* KRB1 */ - ttix_clr_done (ln); /* clear flag */ - dat = dat | ttix_buf[ln]; } /* return buffer */ +if (pulse & 001) { /* KSF1 */ + if (ttix_test_done (ln)) dat = dat | IOT_SKP; + } +if (pulse & 002) { /* KRB1 */ + ttix_clr_done (ln); /* clear flag */ + dat = dat | ttix_buf[ln]; /* return buffer */ + } return dat; } @@ -198,22 +213,26 @@ t_stat ttix_svc (UNIT *uptr) { int32 ln, c, temp; -if ((uptr->flags & UNIT_ATT) == 0) return SCPE_OK; /* attached? */ -sim_activate (uptr, tmxr_poll); /* continue poll */ -ln = tmxr_poll_conn (&ttx_desc); /* look for connect */ -if (ln >= 0) ttx_ldsc[ln].rcve = 1; /* got one? rcv enab */ -tmxr_poll_rx (&ttx_desc); /* poll for input */ -for (ln = 0; ln < TTX_MAXL; 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_KSR) { /* KSR? */ - c = temp & 0177; - if (islower (c)) c = toupper (c); - c = c | 0200; } - else c = temp & ((ttox_unit[ln].flags & UNIT_8B)? 0377: 0177); - ttix_buf[ln] = c; - ttix_set_done (ln); } } } +if ((uptr->flags & UNIT_ATT) == 0) return SCPE_OK; /* attached? */ +sim_activate (uptr, tmxr_poll); /* continue poll */ +ln = tmxr_poll_conn (&ttx_desc); /* look for connect */ +if (ln >= 0) ttx_ldsc[ln].rcve = 1; /* got one? rcv enab */ +tmxr_poll_rx (&ttx_desc); /* poll for input */ +for (ln = 0; ln < TTX_MAXL; 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_KSR) { /* KSR? */ + c = temp & 0177; + if (islower (c)) c = toupper (c); + c = c | 0200; + } + else c = temp & ((ttox_unit[ln].flags & UNIT_8B)? 0377: 0177); + ttix_buf[ln] = c; + ttix_set_done (ln); + } + } + } return SCPE_OK; } @@ -236,23 +255,27 @@ void ttix_clr_done (int32 ln) { ttix_done = ttix_done & ~(1 << ln); if (ttix_done) { SET_INT (TTI1); } -else { CLR_INT (TTI1); } +else { + CLR_INT (TTI1); + } return; } - + /* Terminal output: IOT routine */ int32 ttox (int32 dev, int32 pulse, int32 dat) { -int32 ln = ttx_getln (dev, pulse); /* line # */ +int32 ln = ttx_getln (dev, pulse); /* line # */ if (ln > ttx_lines) return dat; -if (pulse & 001) { /* TSF */ - if (ttox_test_done (ln)) dat = dat | IOT_SKP; } -if (pulse & 002) ttox_clr_done (ln); /* clear flag */ -if (pulse & 004) { /* load buffer */ - sim_activate (&ttox_unit[ln], ttox_unit[ln].wait); /* activate unit */ - ttox_buf[ln] = dat & 0377; } /* load buffer */ +if (pulse & 001) { /* TSF */ + if (ttox_test_done (ln)) dat = dat | IOT_SKP; + } +if (pulse & 002) ttox_clr_done (ln); /* clear flag */ +if (pulse & 004) { /* load buffer */ + sim_activate (&ttox_unit[ln], ttox_unit[ln].wait); /* activate unit */ + ttox_buf[ln] = dat & 0377; /* load buffer */ + } return dat; } @@ -260,23 +283,27 @@ return dat; t_stat ttox_svc (UNIT *uptr) { -int32 c, ln = uptr - ttox_unit; /* line # */ +int32 c, ln = uptr - ttox_unit; /* line # */ -if (ttx_ldsc[ln].conn) { /* connected? */ - if (ttx_ldsc[ln].xmte) { /* tx enabled? */ - TMLN *lp = &ttx_ldsc[ln]; /* get line */ - if (ttox_unit[ln].flags & UNIT_KSR) { /* KSR mode? */ - c = ttox_buf[ln] & 0177; /* get char */ - if (islower (c)) c = toupper (c); - if ((c < 007) || (c > 0137)) c = -1; } - else c = ttox_buf[ln] & ((ttox_unit[ln].flags & UNIT_8B)? 0377: 0177); - if (c >= 0) 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; } } -ttox_set_done (ln); /* set done */ +if (ttx_ldsc[ln].conn) { /* connected? */ + if (ttx_ldsc[ln].xmte) { /* tx enabled? */ + TMLN *lp = &ttx_ldsc[ln]; /* get line */ + if (ttox_unit[ln].flags & UNIT_KSR) { /* KSR mode? */ + c = ttox_buf[ln] & 0177; /* get char */ + if (islower (c)) c = toupper (c); + if ((c < 007) || (c > 0137)) c = -1; + } + else c = ttox_buf[ln] & ((ttox_unit[ln].flags & UNIT_8B)? 0377: 0177); + if (c >= 0) 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; + } + } +ttox_set_done (ln); /* set done */ return SCPE_OK; } @@ -299,10 +326,10 @@ void ttox_clr_done (int32 ln) { ttox_done = ttox_done & ~(1 << ln); if (ttox_done) { SET_INT (TTO1); } -else { CLR_INT (TTO1); } +else { CLR_INT (TTO1); } return; } - + /* Compute relative line number This algorithm does not assign contiguous line numbers of ascending @@ -313,11 +340,11 @@ int32 ttx_getln (int32 dev, int32 pulse) { int32 rdno = ((dev - ttix_dib.dev) >> 1) & 3; -#if defined (PDP15) /* PDP-15? */ +#if defined (PDP15) /* PDP-15? */ int32 sub = (pulse >> 4) & 3; -return (rdno * 4) + sub; /* use dev, subdev */ -#else /* others */ -return rdno; /* use dev only */ +return (rdno * 4) + sub; /* use dev, subdev */ +#else /* others */ +return rdno; /* use dev only */ #endif } @@ -327,15 +354,18 @@ t_stat ttx_reset (DEVICE *dptr) { int32 ln; -if (dptr->flags & DEV_DIS) { /* sync enables */ - 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; } -if (ttix_unit.flags & UNIT_ATT) /* if attached, */ - sim_activate (&ttix_unit, tmxr_poll); /* activate */ -else sim_cancel (&ttix_unit); /* else stop */ -for (ln = 0; ln < TTX_MAXL; ln++) ttx_reset_ln (ln); /* for all lines */ +if (dptr->flags & DEV_DIS) { /* sync enables */ + 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; + } +if (ttix_unit.flags & UNIT_ATT) /* if attached, */ + sim_activate (&ttix_unit, tmxr_poll); /* activate */ +else sim_cancel (&ttix_unit); /* else stop */ +for (ln = 0; ln < TTX_MAXL; ln++) ttx_reset_ln (ln); /* for all lines */ return SCPE_OK; } @@ -343,11 +373,11 @@ return SCPE_OK; void ttx_reset_ln (int32 ln) { -ttix_buf[ln] = 0; /* clear buf, */ +ttix_buf[ln] = 0; /* clear buf, */ ttox_buf[ln] = 0; -ttix_clr_done (ln); /* clear done */ +ttix_clr_done (ln); /* clear done */ ttox_clr_done (ln); -sim_cancel (&ttox_unit[ln]); /* stop poll */ +sim_cancel (&ttox_unit[ln]); /* stop poll */ return; } @@ -357,9 +387,9 @@ t_stat ttx_attach (UNIT *uptr, char *cptr) { t_stat r; -r = tmxr_attach (&ttx_desc, uptr, cptr); /* attach */ -if (r != SCPE_OK) return r; /* error */ -sim_activate (uptr, tmxr_poll); /* start poll */ +r = tmxr_attach (&ttx_desc, uptr, cptr); /* attach */ +if (r != SCPE_OK) return r; /* error */ +sim_activate (uptr, tmxr_poll); /* start poll */ return SCPE_OK; } @@ -370,9 +400,9 @@ t_stat ttx_detach (UNIT *uptr) int32 i; t_stat r; -r = tmxr_detach (&ttx_desc, uptr); /* detach */ -sim_cancel (uptr); /* stop poll */ -for (i = 0; i < TTX_MAXL; i++) ttx_ldsc[i].rcve = 0; /* disable rcv */ +r = tmxr_detach (&ttx_desc, uptr); /* detach */ +sim_cancel (uptr); /* stop poll */ +for (i = 0; i < TTX_MAXL; i++) ttx_ldsc[i].rcve = 0; /* disable rcv */ return r; } @@ -392,14 +422,17 @@ return SCPE_OK; t_stat ttx_show (FILE *st, UNIT *uptr, int32 val, void *desc) { -int32 i; +int32 i, t; -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); } } +for (i = t = 0; i < TTX_MAXL; i++) t = t + (ttx_ldsc[i].conn != 0); +if (t) { + 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; } @@ -416,20 +449,24 @@ newln = get_uint (cptr, 10, TTX_MAXL, &r); if ((r != SCPE_OK) || (newln == ttx_lines)) return r; if (newln == 0) return SCPE_ARG; if (newln < ttx_lines) { - for (i = newln, t = 0; i < ttx_lines; i++) t = t | ttx_ldsc[i].conn; - if (t && !get_yn ("This will disconnect users; proceed [N]?", FALSE)) - return SCPE_OK; - for (i = newln; i < ttx_lines; i++) { - if (ttx_ldsc[i].conn) { - tmxr_linemsg (&ttx_ldsc[i], "\r\nOperator disconnected line\r\n"); - tmxr_reset_ln (&ttx_ldsc[i]); } /* reset line */ - ttox_unit[i].flags = ttox_unit[i].flags | UNIT_DIS; - ttx_reset_ln (i); } - } -else { for (i = ttx_lines; i < newln; i++) { - ttox_unit[i].flags = ttox_unit[i].flags & ~UNIT_DIS; - ttx_reset_ln (i); } - } + for (i = newln, t = 0; i < ttx_lines; i++) t = t | ttx_ldsc[i].conn; + if (t && !get_yn ("This will disconnect users; proceed [N]?", FALSE)) + return SCPE_OK; + for (i = newln; i < ttx_lines; i++) { + if (ttx_ldsc[i].conn) { + tmxr_linemsg (&ttx_ldsc[i], "\r\nOperator disconnected line\r\n"); + tmxr_reset_ln (&ttx_ldsc[i]); /* reset line */ + } + ttox_unit[i].flags = ttox_unit[i].flags | UNIT_DIS; + ttx_reset_ln (i); + } + } +else { + for (i = ttx_lines; i < newln; i++) { + ttox_unit[i].flags = ttox_unit[i].flags & ~UNIT_DIS; + ttx_reset_ln (i); + } + } ttx_lines = newln; return SCPE_OK; } diff --git a/PDP8/pdp8_clk.c b/PDP8/pdp8_clk.c index 5361d9d0..7d9a1dd3 100644 --- a/PDP8/pdp8_clk.c +++ b/PDP8/pdp8_clk.c @@ -1,6 +1,6 @@ /* pdp8_clk.c: PDP-8 real-time clock simulator - Copyright (c) 1993-2004, Robert M Supnik + Copyright (c) 1993-2005, 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"), @@ -19,18 +19,18 @@ 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 + 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 + 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 + 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 */ @@ -39,8 +39,8 @@ 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_tps = 60; /* ticks/second */ +int32 tmxr_poll = 16000; /* term mux poll */ int32 clk (int32 IR, int32 AC); t_stat clk_svc (UNIT *uptr); @@ -50,9 +50,9 @@ 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 + clk_dev CLK device descriptor + clk_unit CLK unit descriptor + clk_reg CLK register list */ DIB clk_dib = { DEV_CLK, 1, { &clk } }; @@ -60,30 +60,33 @@ 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 } }; + { 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 } }; + { 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 }; - + "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 @@ -92,34 +95,43 @@ DEVICE clk_dev = { 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 */ +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 */ @@ -128,11 +140,11 @@ 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 */ +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; } @@ -140,10 +152,10 @@ return SCPE_OK; t_stat clk_reset (DEVICE *dptr) { -dev_done = dev_done & ~INT_CLK; /* clear done, int */ +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 */ +int_enable = int_enable & ~INT_CLK; /* clear enable */ +sim_activate (&clk_unit, clk_unit.wait); /* activate unit */ return SCPE_OK; } diff --git a/PDP8/pdp8_cpu.c b/PDP8/pdp8_cpu.c index c24d50ad..db5ae5d7 100644 --- a/PDP8/pdp8_cpu.c +++ b/PDP8/pdp8_cpu.c @@ -1,6 +1,6 @@ /* pdp8_cpu.c: PDP-8 CPU simulator - Copyright (c) 1993-2004, Robert M Supnik + Copyright (c) 1993-2005, 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"), @@ -19,68 +19,69 @@ 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 + 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 + cpu central processor - 06-Nov-04 RMS Added =n to SHOW HISTORY - 31-Dec-03 RMS Fixed bug in set_cpu_hist - 13-Oct-03 RMS Added instruction history - Added TSC8-75 support (from Bernhard Baehr) - 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 + 16-Aug-05 RMS Fixed C++ declaration and cast problems + 06-Nov-04 RMS Added =n to SHOW HISTORY + 31-Dec-03 RMS Fixed bug in set_cpu_hist + 13-Oct-03 RMS Added instruction history + Added TSC8-75 support (from Bernhard Baehr) + 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 + 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 + | op |in|zr| page offset | memory reference +--+--+--+--+--+--+--+--+--+--+--+--+ - <0:2> mnemonic action + <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 + 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>] + <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. @@ -92,13 +93,12 @@ 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: + + 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 + | op | device | pulse | I/O transfer +--+--+--+--+--+--+--+--+--+--+--+--+ The IO transfer instruction sends the the specified pulse to the @@ -109,45 +109,44 @@ The operate format is as follows: +--+--+--+--+--+--+--+--+--+--+--+--+ - | 1| 1| 1| 0| | | | | | | | | operate group 1 + | 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 + | | | | | | | | + | | | | | | | +--- 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 + | 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 + | | | | | | | + | | | | | | +--- 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 + | 1| 1| 1| 1| | | | | | | | 1| operate group 3 +--+--+--+--+--+--+--+--+--+--+--+--+ - | | | | \______/ - | | | | | - | | +--|-----+--- EAE command 3 - | | +--- AC -> MQ, 0 -> AC 2 - | +--- MQ v AC --> AC 2 - +-- clear AC 1 + | | | | \______/ + | | | | | + | | +--|-----+--- 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. + + 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. @@ -156,16 +155,16 @@ 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 + 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 + 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 @@ -180,63 +179,65 @@ 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 + 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] = MA -#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) +#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] = MA +#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) -#define HIST_PC 0x40000000 -#define HIST_MIN 64 -#define HIST_MAX 65536 -struct InstHistory { - int32 pc; - int32 ea; - int16 ir; - int16 opnd; - int16 lac; - int16 mq; }; +#define HIST_PC 0x40000000 +#define HIST_MIN 64 +#define HIST_MAX 65536 -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 */ -int32 tsc_ir = 0; /* TSC8-75 IR */ -int32 tsc_pc = 0; /* TSC8-75 PC */ -int32 tsc_cdf = 0; /* TSC8-75 CDF flag */ -int32 tsc_enb = 0; /* TSC8-75 enabled */ -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 */ -int32 hst_p = 0; /* history pointer */ -int32 hst_lnt = 0; /* history length */ -struct InstHistory *hst = NULL; /* instruction history */ +typedef struct { + int32 pc; + int32 ea; + int16 ir; + int16 opnd; + int16 lac; + int16 mq; + } InstHistory; + +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 */ +int32 tsc_ir = 0; /* TSC8-75 IR */ +int32 tsc_pc = 0; /* TSC8-75 PC */ +int32 tsc_cdf = 0; /* TSC8-75 CDF flag */ +int32 tsc_enb = 0; /* TSC8-75 enabled */ +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 */ +int32 hst_p = 0; /* history pointer */ +int32 hst_lnt = 0; /* history length */ +InstHistory *hst = NULL; /* instruction history */ extern int32 sim_interval; extern int32 sim_int_char; -extern int32 sim_brk_types, sim_brk_dflt, sim_brk_summ; /* breakpoint info */ +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; @@ -248,68 +249,71 @@ 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); 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 + 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 } }; + { 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 }, - { MTAB_XTD|MTAB_VDV|MTAB_NMO|MTAB_SHP, 0, "HISTORY", "HISTORY", - &cpu_set_hist, &cpu_show_hist }, - { 0 } }; + { 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 }, + { MTAB_XTD|MTAB_VDV|MTAB_NMO|MTAB_SHP, 0, "HISTORY", "HISTORY", + &cpu_set_hist, &cpu_show_hist }, + { 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 }; - + "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; @@ -319,41 +323,45 @@ t_stat reason; /* Restore register state */ -if (build_dev_tab ()) return SCPE_STOP; /* build dev_tab */ -PC = saved_PC & 007777; /* load local copies */ +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 */ +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; } +while (reason == 0) { /* loop until halted */ -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 */ + if (sim_interval <= 0) { /* check clock queue */ + if (reason = sim_process_event ()) break; + } -MA = IF | PC; /* form PC */ -if (sim_brk_summ && sim_brk_test (MA, SWMASK ('E'))) { /* breakpoint? */ - reason = STOP_IBKPT; /* stop simulation */ - 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; -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>) @@ -371,135 +379,149 @@ sim_interval = sim_interval - 1; Note that MA contains IF'PC. */ -if (hst_lnt) { /* history enabled? */ - int32 ea; + if (hst_lnt) { /* history enabled? */ + int32 ea; - hst_p = (hst_p + 1); /* next entry */ - if (hst_p >= hst_lnt) hst_p = 0; - hst[hst_p].pc = MA | HIST_PC; /* save PC, IR, LAC, MQ */ - hst[hst_p].ir = IR; - hst[hst_p].lac = LAC; - hst[hst_p].mq = MQ; - if (IR < 06000) { /* mem ref? */ - if (IR & 0200) ea = (MA & 077600) | (IR & 0177); - else ea = IF | (IR & 0177); /* direct addr */ - if (IR & 0400) { /* indirect? */ - if (IR < 04000) { /* mem operand? */ - if ((ea & 07770) != 00010) ea = DF | M[ea]; - else ea = DF | ((M[ea] + 1) & 07777); } - else { /* no, jms/jmp */ - if ((ea & 07770) != 00010) ea = IB | M[ea]; - else ea = IB | ((M[ea] + 1) & 07777); } - } - hst[hst_p].ea = ea; /* save eff addr */ - hst[hst_p].opnd = M[ea]; /* save operand */ - } - } + hst_p = (hst_p + 1); /* next entry */ + if (hst_p >= hst_lnt) hst_p = 0; + hst[hst_p].pc = MA | HIST_PC; /* save PC, IR, LAC, MQ */ + hst[hst_p].ir = IR; + hst[hst_p].lac = LAC; + hst[hst_p].mq = MQ; + if (IR < 06000) { /* mem ref? */ + if (IR & 0200) ea = (MA & 077600) | (IR & 0177); + else ea = IF | (IR & 0177); /* direct addr */ + if (IR & 0400) { /* indirect? */ + if (IR < 04000) { /* mem operand? */ + if ((ea & 07770) != 00010) ea = DF | M[ea]; + else ea = DF | ((M[ea] + 1) & 07777); + } + else { /* no, jms/jmp */ + if ((ea & 07770) != 00010) ea = IB | M[ea]; + else ea = IB | ((M[ea] + 1) & 07777); + } + } + hst[hst_p].ea = ea; /* save eff addr */ + hst[hst_p].opnd = M[ea]; /* save operand */ + } + } + +switch ((IR >> 7) & 037) { /* decode IR<0:4> */ -switch ((IR >> 7) & 037) { /* decode IR<0:4> */ - /* Opcode 0, AND */ -case 000: /* AND, dir, zero */ - MA = IF | (IR & 0177); /* dir addr, page zero */ - LAC = LAC & (M[MA] | 010000); - break; -case 001: /* AND, dir, curr */ - MA = (MA & 077600) | (IR & 0177); /* dir addr, curr page */ - LAC = LAC & (M[MA] | 010000); - break; -case 002: /* AND, indir, zero */ - MA = IF | (IR & 0177); /* dir addr, page zero */ - if ((MA & 07770) != 00010) MA = DF | M[MA]; /* indirect; autoinc? */ - else MA = DF | (M[MA] = (M[MA] + 1) & 07777); /* incr before use */ - LAC = LAC & (M[MA] | 010000); - break; -case 003: /* AND, indir, curr */ - MA = (MA & 077600) | (IR & 0177); /* dir addr, curr page */ - if ((MA & 07770) != 00010) MA = DF | M[MA]; /* indirect; autoinc? */ - else MA = DF | (M[MA] = (M[MA] + 1) & 07777); /* incr before use */ - LAC = LAC & (M[MA] | 010000); - break; + case 000: /* AND, dir, zero */ + MA = IF | (IR & 0177); /* dir addr, page zero */ + LAC = LAC & (M[MA] | 010000); + break; + + case 001: /* AND, dir, curr */ + MA = (MA & 077600) | (IR & 0177); /* dir addr, curr page */ + LAC = LAC & (M[MA] | 010000); + break; + + case 002: /* AND, indir, zero */ + MA = IF | (IR & 0177); /* dir addr, page zero */ + if ((MA & 07770) != 00010) MA = DF | M[MA]; /* indirect; autoinc? */ + else MA = DF | (M[MA] = (M[MA] + 1) & 07777); /* incr before use */ + LAC = LAC & (M[MA] | 010000); + break; + + case 003: /* AND, indir, curr */ + MA = (MA & 077600) | (IR & 0177); /* dir addr, curr page */ + if ((MA & 07770) != 00010) MA = DF | M[MA]; /* indirect; autoinc? */ + else MA = DF | (M[MA] = (M[MA] + 1) & 07777); /* incr before use */ + LAC = LAC & (M[MA] | 010000); + break; /* Opcode 1, TAD */ -case 004: /* TAD, dir, zero */ - MA = IF | (IR & 0177); /* dir addr, page zero */ - LAC = (LAC + M[MA]) & 017777; - break; -case 005: /* TAD, dir, curr */ - MA = (MA & 077600) | (IR & 0177); /* dir addr, curr page */ - LAC = (LAC + M[MA]) & 017777; - break; -case 006: /* TAD, indir, zero */ - MA = IF | (IR & 0177); /* dir addr, page zero */ - if ((MA & 07770) != 00010) MA = DF | M[MA]; /* indirect; autoinc? */ - else MA = DF | (M[MA] = (M[MA] + 1) & 07777); /* incr before use */ - LAC = (LAC + M[MA]) & 017777; - break; -case 007: /* TAD, indir, curr */ - MA = (MA & 077600) | (IR & 0177); /* dir addr, curr page */ - if ((MA & 07770) != 00010) MA = DF | M[MA]; /* indirect; autoinc? */ - else MA = DF | (M[MA] = (M[MA] + 1) & 07777); /* incr before use */ - LAC = (LAC + M[MA]) & 017777; - break; - + case 004: /* TAD, dir, zero */ + MA = IF | (IR & 0177); /* dir addr, page zero */ + LAC = (LAC + M[MA]) & 017777; + break; + + case 005: /* TAD, dir, curr */ + MA = (MA & 077600) | (IR & 0177); /* dir addr, curr page */ + LAC = (LAC + M[MA]) & 017777; + break; + + case 006: /* TAD, indir, zero */ + MA = IF | (IR & 0177); /* dir addr, page zero */ + if ((MA & 07770) != 00010) MA = DF | M[MA]; /* indirect; autoinc? */ + else MA = DF | (M[MA] = (M[MA] + 1) & 07777); /* incr before use */ + LAC = (LAC + M[MA]) & 017777; + break; + + case 007: /* TAD, indir, curr */ + MA = (MA & 077600) | (IR & 0177); /* dir addr, curr page */ + if ((MA & 07770) != 00010) MA = DF | M[MA]; /* indirect; autoinc? */ + else MA = DF | (M[MA] = (M[MA] + 1) & 07777); /* incr before use */ + LAC = (LAC + M[MA]) & 017777; + break; + /* Opcode 2, ISZ */ -case 010: /* ISZ, dir, zero */ - MA = IF | (IR & 0177); /* dir addr, page zero */ - M[MA] = MB = (M[MA] + 1) & 07777; /* field must exist */ - if (MB == 0) PC = (PC + 1) & 07777; - break; -case 011: /* ISZ, dir, curr */ - MA = (MA & 077600) | (IR & 0177); /* dir addr, 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 */ - MA = IF | (IR & 0177); /* dir addr, page zero */ - if ((MA & 07770) != 00010) MA = DF | M[MA]; /* indirect; autoinc? */ - else MA = DF | (M[MA] = (M[MA] + 1) & 07777); /* incr before use */ - 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 */ - MA = (MA & 077600) | (IR & 0177); /* dir addr, curr page */ - if ((MA & 07770) != 00010) MA = DF | M[MA]; /* indirect; autoinc? */ - else MA = DF | (M[MA] = (M[MA] + 1) & 07777); /* incr before use */ - MB = (M[MA] + 1) & 07777; - if (MEM_ADDR_OK (MA)) M[MA] = MB; - if (MB == 0) PC = (PC + 1) & 07777; - break; + case 010: /* ISZ, dir, zero */ + MA = IF | (IR & 0177); /* dir addr, page zero */ + M[MA] = MB = (M[MA] + 1) & 07777; /* field must exist */ + if (MB == 0) PC = (PC + 1) & 07777; + break; + + case 011: /* ISZ, dir, curr */ + MA = (MA & 077600) | (IR & 0177); /* dir addr, 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 */ + MA = IF | (IR & 0177); /* dir addr, page zero */ + if ((MA & 07770) != 00010) MA = DF | M[MA]; /* indirect; autoinc? */ + else MA = DF | (M[MA] = (M[MA] + 1) & 07777); /* incr before use */ + 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 */ + MA = (MA & 077600) | (IR & 0177); /* dir addr, curr page */ + if ((MA & 07770) != 00010) MA = DF | M[MA]; /* indirect; autoinc? */ + else MA = DF | (M[MA] = (M[MA] + 1) & 07777); /* incr before use */ + 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 */ - MA = IF | (IR & 0177); /* dir addr, page zero */ - M[MA] = LAC & 07777; - LAC = LAC & 010000; - break; -case 015: /* DCA, dir, curr */ - MA = (MA & 077600) | (IR & 0177); /* dir addr, curr page */ - M[MA] = LAC & 07777; - LAC = LAC & 010000; - break; -case 016: /* DCA, indir, zero */ - MA = IF | (IR & 0177); /* dir addr, page zero */ - if ((MA & 07770) != 00010) MA = DF | M[MA]; /* indirect; autoinc? */ - else MA = DF | (M[MA] = (M[MA] + 1) & 07777); /* incr before use */ - if (MEM_ADDR_OK (MA)) M[MA] = LAC & 07777; - LAC = LAC & 010000; - break; -case 017: /* DCA, indir, curr */ - MA = (MA & 077600) | (IR & 0177); /* dir addr, curr page */ - if ((MA & 07770) != 00010) MA = DF | M[MA]; /* indirect; autoinc? */ - else MA = DF | (M[MA] = (M[MA] + 1) & 07777); /* incr before use */ - if (MEM_ADDR_OK (MA)) M[MA] = LAC & 07777; - LAC = LAC & 010000; - break; - + case 014: /* DCA, dir, zero */ + MA = IF | (IR & 0177); /* dir addr, page zero */ + M[MA] = LAC & 07777; + LAC = LAC & 010000; + break; + + case 015: /* DCA, dir, curr */ + MA = (MA & 077600) | (IR & 0177); /* dir addr, curr page */ + M[MA] = LAC & 07777; + LAC = LAC & 010000; + break; + + case 016: /* DCA, indir, zero */ + MA = IF | (IR & 0177); /* dir addr, page zero */ + if ((MA & 07770) != 00010) MA = DF | M[MA]; /* indirect; autoinc? */ + else MA = DF | (M[MA] = (M[MA] + 1) & 07777); /* incr before use */ + if (MEM_ADDR_OK (MA)) M[MA] = LAC & 07777; + LAC = LAC & 010000; + break; + + case 017: /* DCA, indir, curr */ + MA = (MA & 077600) | (IR & 0177); /* dir addr, curr page */ + if ((MA & 07770) != 00010) MA = DF | M[MA]; /* indirect; autoinc? */ + else MA = DF | (M[MA] = (M[MA] + 1) & 07777); /* incr before use */ + if (MEM_ADDR_OK (MA)) M[MA] = LAC & 07777; + LAC = LAC & 010000; + break; + /* Opcode 4, JMS. From Bernhard Baehr's description of the TSC8-75: (In user mode) the current JMS opcode is moved to the ERIOT register, the ECDF @@ -510,79 +532,94 @@ case 017: /* DCA, indir, curr */ word of the subroutine) happens. When the TSC8-75 is disabled, the JMS is performed as usual. */ -case 020: /* JMS, dir, zero */ - PCQ_ENTRY; - MA = IR & 0177; /* dir addr, page zero */ - if (UF) { /* user mode? */ - tsc_ir = IR; /* save instruction */ - tsc_cdf = 0; } /* clear flag */ - if (UF && tsc_enb) { /* user mode, TSC enab? */ - tsc_pc = (PC - 1) & 07777; /* save PC */ - int_req = int_req | INT_TSC; } /* request intr */ - else { /* normal */ - IF = IB; /* change IF */ - UF = UB; /* change UF */ - int_req = int_req | INT_NO_CIF_PENDING; /* clr intr inhibit */ - MA = IF | MA; - if (MEM_ADDR_OK (MA)) M[MA] = PC; } - PC = (MA + 1) & 07777; - break; -case 021: /* JMS, dir, curr */ - PCQ_ENTRY; - MA = (MA & 007600) | (IR & 0177); /* dir addr, curr page */ - if (UF) { /* user mode? */ - tsc_ir = IR; /* save instruction */ - tsc_cdf = 0; } /* clear flag */ - if (UF && tsc_enb) { /* user mode, TSC enab? */ - tsc_pc = (PC - 1) & 07777; /* save PC */ - int_req = int_req | INT_TSC; } /* request intr */ - else { /* normal */ - IF = IB; /* change IF */ - UF = UB; /* change UF */ - int_req = int_req | INT_NO_CIF_PENDING; /* clr intr inhibit */ - MA = IF | MA; - if (MEM_ADDR_OK (MA)) M[MA] = PC; } - PC = (MA + 1) & 07777; - break; -case 022: /* JMS, indir, zero */ - PCQ_ENTRY; - MA = IF | (IR & 0177); /* dir addr, page zero */ - if ((MA & 07770) != 00010) MA = M[MA]; /* indirect; autoinc? */ - else MA = (M[MA] = (M[MA] + 1) & 07777); /* incr before use */ - if (UF) { /* user mode? */ - tsc_ir = IR; /* save instruction */ - tsc_cdf = 0; } /* clear flag */ - if (UF && tsc_enb) { /* user mode, TSC enab? */ - tsc_pc = (PC - 1) & 07777; /* save PC */ - int_req = int_req | INT_TSC; } /* request intr */ - else { /* normal */ - IF = IB; /* change IF */ - UF = UB; /* change UF */ - int_req = int_req | INT_NO_CIF_PENDING; /* clr intr inhibit */ - MA = IF | MA; - if (MEM_ADDR_OK (MA)) M[MA] = PC; } - PC = (MA + 1) & 07777; - break; -case 023: /* JMS, indir, curr */ - PCQ_ENTRY; - MA = (MA & 077600) | (IR & 0177); /* dir addr, curr page */ - if ((MA & 07770) != 00010) MA = M[MA]; /* indirect; autoinc? */ - else MA = (M[MA] = (M[MA] + 1) & 07777); /* incr before use */ - if (UF) { /* user mode? */ - tsc_ir = IR; /* save instruction */ - tsc_cdf = 0; } /* clear flag */ - if (UF && tsc_enb) { /* user mode, TSC enab? */ - tsc_pc = (PC - 1) & 07777; /* save PC */ - int_req = int_req | INT_TSC; } /* request intr */ - else { /* normal */ - IF = IB; /* change IF */ - UF = UB; /* change UF */ - int_req = int_req | INT_NO_CIF_PENDING; /* clr intr inhibit */ - MA = IF | MA; - if (MEM_ADDR_OK (MA)) M[MA] = PC; } - PC = (MA + 1) & 07777; - break; - + case 020: /* JMS, dir, zero */ + PCQ_ENTRY; + MA = IR & 0177; /* dir addr, page zero */ + if (UF) { /* user mode? */ + tsc_ir = IR; /* save instruction */ + tsc_cdf = 0; /* clear flag */ + } + if (UF && tsc_enb) { /* user mode, TSC enab? */ + tsc_pc = (PC - 1) & 07777; /* save PC */ + int_req = int_req | INT_TSC; /* request intr */ + } + else { /* normal */ + IF = IB; /* change IF */ + UF = UB; /* change UF */ + int_req = int_req | INT_NO_CIF_PENDING; /* clr intr inhibit */ + MA = IF | MA; + if (MEM_ADDR_OK (MA)) M[MA] = PC; + } + PC = (MA + 1) & 07777; + break; + + case 021: /* JMS, dir, curr */ + PCQ_ENTRY; + MA = (MA & 007600) | (IR & 0177); /* dir addr, curr page */ + if (UF) { /* user mode? */ + tsc_ir = IR; /* save instruction */ + tsc_cdf = 0; /* clear flag */ + } + if (UF && tsc_enb) { /* user mode, TSC enab? */ + tsc_pc = (PC - 1) & 07777; /* save PC */ + int_req = int_req | INT_TSC; /* request intr */ + } + else { /* normal */ + IF = IB; /* change IF */ + UF = UB; /* change UF */ + int_req = int_req | INT_NO_CIF_PENDING; /* clr intr inhibit */ + MA = IF | MA; + if (MEM_ADDR_OK (MA)) M[MA] = PC; + } + PC = (MA + 1) & 07777; + break; + + case 022: /* JMS, indir, zero */ + PCQ_ENTRY; + MA = IF | (IR & 0177); /* dir addr, page zero */ + if ((MA & 07770) != 00010) MA = M[MA]; /* indirect; autoinc? */ + else MA = (M[MA] = (M[MA] + 1) & 07777); /* incr before use */ + if (UF) { /* user mode? */ + tsc_ir = IR; /* save instruction */ + tsc_cdf = 0; /* clear flag */ + } + if (UF && tsc_enb) { /* user mode, TSC enab? */ + tsc_pc = (PC - 1) & 07777; /* save PC */ + int_req = int_req | INT_TSC; /* request intr */ + } + else { /* normal */ + IF = IB; /* change IF */ + UF = UB; /* change UF */ + int_req = int_req | INT_NO_CIF_PENDING; /* clr intr inhibit */ + MA = IF | MA; + if (MEM_ADDR_OK (MA)) M[MA] = PC; + } + PC = (MA + 1) & 07777; + break; + + case 023: /* JMS, indir, curr */ + PCQ_ENTRY; + MA = (MA & 077600) | (IR & 0177); /* dir addr, curr page */ + if ((MA & 07770) != 00010) MA = M[MA]; /* indirect; autoinc? */ + else MA = (M[MA] = (M[MA] + 1) & 07777); /* incr before use */ + if (UF) { /* user mode? */ + tsc_ir = IR; /* save instruction */ + tsc_cdf = 0; /* clear flag */ + } + if (UF && tsc_enb) { /* user mode, TSC enab? */ + tsc_pc = (PC - 1) & 07777; /* save PC */ + int_req = int_req | INT_TSC; /* request intr */ + } + else { /* normal */ + IF = IB; /* change IF */ + UF = UB; /* change UF */ + int_req = int_req | INT_NO_CIF_PENDING; /* clr intr inhibit */ + MA = IF | MA; + if (MEM_ADDR_OK (MA)) M[MA] = PC; + } + PC = (MA + 1) & 07777; + break; + /* Opcode 5, JMP. From Bernhard Baehr's description of the TSC8-75: (In user mode) the current JMP opcode is moved to the ERIOT register, the ECDF @@ -590,242 +627,259 @@ case 023: /* JMS, indir, curr */ register and the TSC8-75 I/O flag is raised. Then the JMP is performed as usual (including the setting of IF, UF and clearing the interrupt inhibit flag). */ -case 024: /* JMP, dir, zero */ - PCQ_ENTRY; - MA = IR & 0177; /* dir addr, page zero */ - if (UF) { /* user mode? */ - tsc_ir = IR; /* save instruction */ - tsc_cdf = 0; /* clear flag */ - if (tsc_enb) { /* TSC8 enabled? */ - tsc_pc = (PC - 1) & 07777; /* save PC */ - int_req = int_req | INT_TSC; } } /* request intr */ - IF = IB; /* change IF */ - UF = UB; /* change UF */ - int_req = int_req | INT_NO_CIF_PENDING; /* clr intr inhibit */ - PC = MA; - break; -case 025: /* JMP, dir, curr */ - PCQ_ENTRY; - MA = (MA & 007600) | (IR & 0177); /* dir addr, curr page */ - if (UF) { /* user mode? */ - tsc_ir = IR; /* save instruction */ - tsc_cdf = 0; /* clear flag */ - if (tsc_enb) { /* TSC8 enabled? */ - tsc_pc = (PC - 1) & 07777; /* save PC */ - int_req = int_req | INT_TSC; } } /* request intr */ - IF = IB; /* change IF */ - UF = UB; /* change UF */ - int_req = int_req | INT_NO_CIF_PENDING; /* clr intr inhibit */ - PC = MA; - break; -case 026: /* JMP, indir, zero */ - PCQ_ENTRY; - MA = IF | (IR & 0177); /* dir addr, page zero */ - if ((MA & 07770) != 00010) MA = M[MA]; /* indirect; autoinc? */ - else MA = (M[MA] = (M[MA] + 1) & 07777); /* incr before use */ - if (UF) { /* user mode? */ - tsc_ir = IR; /* save instruction */ - tsc_cdf = 0; /* clear flag */ - if (tsc_enb) { /* TSC8 enabled? */ - tsc_pc = (PC - 1) & 07777; /* save PC */ - int_req = int_req | INT_TSC; } } /* request intr */ - IF = IB; /* change IF */ - UF = UB; /* change UF */ - int_req = int_req | INT_NO_CIF_PENDING; /* clr intr inhibit */ - PC = MA; - break; -case 027: /* JMP, indir, curr */ - PCQ_ENTRY; - MA = (MA & 077600) | (IR & 0177); /* dir addr, curr page */ - if ((MA & 07770) != 00010) MA = M[MA]; /* indirect; autoinc? */ - else MA = (M[MA] = (M[MA] + 1) & 07777); /* incr before use */ - if (UF) { /* user mode? */ - tsc_ir = IR; /* save instruction */ - tsc_cdf = 0; /* clear flag */ - if (tsc_enb) { /* TSC8 enabled? */ - tsc_pc = (PC - 1) & 07777; /* save PC */ - int_req = int_req | INT_TSC; } } /* request intr */ - IF = IB; /* change IF */ - UF = UB; /* change UF */ - int_req = int_req | INT_NO_CIF_PENDING; /* clr intr inhibit */ - PC = MA; - break; - + case 024: /* JMP, dir, zero */ + PCQ_ENTRY; + MA = IR & 0177; /* dir addr, page zero */ + if (UF) { /* user mode? */ + tsc_ir = IR; /* save instruction */ + tsc_cdf = 0; /* clear flag */ + if (tsc_enb) { /* TSC8 enabled? */ + tsc_pc = (PC - 1) & 07777; /* save PC */ + int_req = int_req | INT_TSC; /* request intr */ + } + } + IF = IB; /* change IF */ + UF = UB; /* change UF */ + int_req = int_req | INT_NO_CIF_PENDING; /* clr intr inhibit */ + PC = MA; + break; + + case 025: /* JMP, dir, curr */ + PCQ_ENTRY; + MA = (MA & 007600) | (IR & 0177); /* dir addr, curr page */ + if (UF) { /* user mode? */ + tsc_ir = IR; /* save instruction */ + tsc_cdf = 0; /* clear flag */ + if (tsc_enb) { /* TSC8 enabled? */ + tsc_pc = (PC - 1) & 07777; /* save PC */ + int_req = int_req | INT_TSC; /* request intr */ + } + } + IF = IB; /* change IF */ + UF = UB; /* change UF */ + int_req = int_req | INT_NO_CIF_PENDING; /* clr intr inhibit */ + PC = MA; + break; + + case 026: /* JMP, indir, zero */ + PCQ_ENTRY; + MA = IF | (IR & 0177); /* dir addr, page zero */ + if ((MA & 07770) != 00010) MA = M[MA]; /* indirect; autoinc? */ + else MA = (M[MA] = (M[MA] + 1) & 07777); /* incr before use */ + if (UF) { /* user mode? */ + tsc_ir = IR; /* save instruction */ + tsc_cdf = 0; /* clear flag */ + if (tsc_enb) { /* TSC8 enabled? */ + tsc_pc = (PC - 1) & 07777; /* save PC */ + int_req = int_req | INT_TSC; /* request intr */ + } + } + IF = IB; /* change IF */ + UF = UB; /* change UF */ + int_req = int_req | INT_NO_CIF_PENDING; /* clr intr inhibit */ + PC = MA; + break; + + case 027: /* JMP, indir, curr */ + PCQ_ENTRY; + MA = (MA & 077600) | (IR & 0177); /* dir addr, curr page */ + if ((MA & 07770) != 00010) MA = M[MA]; /* indirect; autoinc? */ + else MA = (M[MA] = (M[MA] + 1) & 07777); /* incr before use */ + if (UF) { /* user mode? */ + tsc_ir = IR; /* save instruction */ + tsc_cdf = 0; /* clear flag */ + if (tsc_enb) { /* TSC8 enabled? */ + tsc_pc = (PC - 1) & 07777; /* save PC */ + int_req = int_req | INT_TSC; /* request intr */ + } + } + IF = IB; /* change IF */ + UF = UB; /* change UF */ + int_req = int_req | INT_NO_CIF_PENDING; /* clr intr inhibit */ + 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 */ + 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 */ + + 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 */ + } /* end switch shifts */ + break; /* end group 1 */ - 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. From Bernhard Baehr's description of the TSC8-75: (In user mode) HLT (7402), OSR (7404) and microprogrammed combinations with HLT and OSR: Additional to raising a user mode interrupt, the current OPR opcode is moved to the ERIOT register and the ECDF flag is cleared. */ -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) { /* user mode? */ - int_req = int_req | INT_UF; /* request intr */ - tsc_ir = IR; /* save instruction */ - tsc_cdf = 0; } /* clear flag */ - else { - if (IR & 04) LAC = LAC | OSR; /* OSR */ - if (IR & 02) reason = STOP_HALT; } /* HLT */ - break; } /* end 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) { /* user mode? */ + int_req = int_req | INT_UF; /* request intr */ + tsc_ir = IR; /* save instruction */ + tsc_cdf = 0; /* clear flag */ + } + else { + if (IR & 04) LAC = LAC | OSR; /* OSR */ + if (IR & 02) reason = STOP_HALT; /* HLT */ + } + break; + } /* end if 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; + 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; } - + 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 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. @@ -836,340 +890,383 @@ case 036:case 037: /* OPR, groups 2, 3 */ 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 (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 + <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 + 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; - if ((MA & 07770) != 00010) MA = DF | M[MA]; /* indirect; autoinc? */ - else MA = DF | (M[MA] = (M[MA] + 1) & 07777); /* incr before use */ - 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; - if ((MA & 07770) != 00010) MA = DF | M[MA]; /* indirect; autoinc? */ - else MA = DF | (M[MA] = (M[MA] + 1) & 07777); /* incr before use */ - 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) { /* mode B: defer */ - if ((MA & 07770) != 00010) MA = DF | M[MA]; /* indirect; autoinc? */ - else MA = DF | (M[MA] = (M[MA] + 1) & 07777); /* incr before use */ - } - temp = (MQ * M[MA]) + (LAC & 07777); - LAC = (temp >> 12) & 07777; - MQ = temp & 07777; - PC = (PC + 1) & 07777; - SC = 014; /* 12 shifts */ - break; - -/* EAE continued */ + if (emode == 0) gtf = 0; /* mode A? clr gtf */ + switch ((IR >> 1) & 027) { /* decode IR<6,8:10> */ - case 023: /* mode B: SWBA */ - if (emode) break; - LAC = LAC | SC; /* mode A: SCA then */ - case 003: /* DVI */ - MA = IF | PC; - if (emode) { /* mode B: defer */ - if ((MA & 07770) != 00010) MA = DF | M[MA]; /* indirect; autoinc? */ - else MA = DF | (M[MA] = (M[MA] + 1) & 07777); /* incr before use */ - } - 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 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; + if ((MA & 07770) != 00010) MA = DF | M[MA]; /* indirect; autoinc? */ + else MA = DF | (M[MA] = (M[MA] + 1) & 07777); /* incr before use */ + 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; + if ((MA & 07770) != 00010) MA = DF | M[MA]; /* indirect; autoinc? */ + else MA = DF | (M[MA] = (M[MA] + 1) & 07777); /* incr before use */ + 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) { /* mode B: defer */ + if ((MA & 07770) != 00010) MA = DF | M[MA]; /* indirect; autoinc? */ + else MA = DF | (M[MA] = (M[MA] + 1) & 07777); /* incr before use */ + } + temp = (MQ * M[MA]) + (LAC & 07777); + LAC = (temp >> 12) & 07777; + MQ = temp & 07777; + PC = (PC + 1) & 07777; + SC = 014; /* 12 shifts */ + break; + + case 023: /* mode B: SWBA */ + if (emode) break; + LAC = LAC | SC; /* mode A: SCA then */ + case 003: /* DVI */ + MA = IF | PC; + if (emode) { /* mode B: defer */ + if ((MA & 07770) != 00010) MA = DF | M[MA]; /* indirect; autoinc? */ + else MA = DF | (M[MA] = (M[MA] + 1) & 07777); /* incr before use */ + } + 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; + + 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 */ - 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. From Bernhard Baehr's description of the TSC8-75: (In user mode) Additional to raising a user mode interrupt, the current IOT opcode is moved to the ERIOT register. When the IOT is a CDF instruction (62x1), the ECDF flag is set, otherwise it is cleared. */ -case 030:case 031:case 032:case 033: /* IOT */ - if (UF) { /* privileged? */ - int_req = int_req | INT_UF; /* request intr */ - tsc_ir = IR; /* save instruction */ - if ((IR & 07707) == 06201) tsc_cdf = 1; /* set/clear flag */ - else tsc_cdf = 0; - 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; - reset_all (1); /* reset all dev */ - break; } /* end switch pulse */ - break; /* end case 0 */ - -/* IOT, continued: memory extension */ + case 030:case 031:case 032:case 033: /* IOT */ + if (UF) { /* privileged? */ + int_req = int_req | INT_UF; /* request intr */ + tsc_ir = IR; /* save instruction */ + if ((IR & 07707) == 06201) tsc_cdf = 1; /* set/clear flag */ + else tsc_cdf = 0; + 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 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 000: /* 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; + reset_all (1); /* reset all dev */ + break; + } /* end switch pulse */ + break; /* end case 0 */ + + 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 */ + + 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 */ - 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_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 */ +pcq_r->qptr = pcq_p; /* update pc q ptr */ return reason; -} /* end sim_instr */ +} /* end sim_instr */ /* Reset routine */ @@ -1211,10 +1308,10 @@ int32 mc = 0; uint32 i; if ((val <= 0) || (val > MAXMEMSIZE) || ((val & 07777) != 0)) - return SCPE_ARG; + 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; + return SCPE_OK; MEMSIZE = val; for (i = MEMSIZE; i < MAXMEMSIZE; i++) M[i] = 0; return SCPE_OK; @@ -1235,9 +1332,9 @@ 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 */ +newdev = get_uint (cptr, 8, DEV_MAX - 1, &r); /* get new */ if ((r != SCPE_OK) || (newdev == dibp->dev)) return r; -dibp->dev = newdev; /* store */ +dibp->dev = newdev; /* store */ return SCPE_OK; } @@ -1262,7 +1359,7 @@ return SCPE_OK; int32 bad_dev (int32 IR, int32 AC) { -return (SCPE_IERR << IOT_V_REASON) | AC; /* broken! */ +return (SCPE_IERR << IOT_V_REASON) | AC; /* broken! */ } /* Build device dispatch table */ @@ -1272,29 +1369,31 @@ 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 }; +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 */ +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; } @@ -1306,20 +1405,23 @@ int32 i, lnt; t_stat r; if (cptr == NULL) { - for (i = 0; i < hst_lnt; i++) hst[i].pc = 0; - hst_p = 0; - return SCPE_OK; } + for (i = 0; i < hst_lnt; i++) hst[i].pc = 0; + hst_p = 0; + return SCPE_OK; + } lnt = (int32) get_uint (cptr, 10, HIST_MAX, &r); if ((r != SCPE_OK) || (lnt && (lnt < HIST_MIN))) return SCPE_ARG; hst_p = 0; if (hst_lnt) { - free (hst); - hst_lnt = 0; - hst = NULL; } + free (hst); + hst_lnt = 0; + hst = NULL; + } if (lnt) { - hst = calloc (sizeof (struct InstHistory), lnt); - if (hst == NULL) return SCPE_MEM; - hst_lnt = lnt; } + hst = (InstHistory *) calloc (lnt, sizeof (InstHistory)); + if (hst == NULL) return SCPE_MEM; + hst_lnt = lnt; + } return SCPE_OK; } @@ -1331,31 +1433,32 @@ int32 l, k, di, lnt; char *cptr = (char *) desc; t_stat r; t_value sim_eval; -struct InstHistory *h; +InstHistory *h; extern t_stat fprint_sym (FILE *ofile, t_addr addr, t_value *val, - UNIT *uptr, int32 sw); + UNIT *uptr, int32 sw); -if (hst_lnt == 0) return SCPE_NOFNC; /* enabled? */ +if (hst_lnt == 0) return SCPE_NOFNC; /* enabled? */ if (cptr) { - lnt = (int32) get_uint (cptr, 10, hst_lnt, &r); - if ((r != SCPE_OK) || (lnt == 0)) return SCPE_ARG; } + lnt = (int32) get_uint (cptr, 10, hst_lnt, &r); + if ((r != SCPE_OK) || (lnt == 0)) return SCPE_ARG; + } else lnt = hst_lnt; -di = hst_p - lnt; /* work forward */ +di = hst_p - lnt; /* work forward */ if (di < 0) di = di + hst_lnt; fprintf (st, "PC L AC MQ ea IR\n\n"); -for (k = 0; k < lnt; k++) { /* print specified */ - h = &hst[(++di) % hst_lnt]; /* entry pointer */ - if (h->pc & HIST_PC) { /* instruction? */ - l = (h->lac >> 12) & 1; /* link */ - fprintf (st, "%05o %o %04o %04o ", h->pc & ADDRMASK, l, h->lac & 07777, h->mq); - if (h->ir < 06000) fprintf (st, "%05o ", h->ea); - else fprintf (st, " "); - sim_eval = h->ir; - if ((fprint_sym (st, h->pc & ADDRMASK, &sim_eval, &cpu_unit, SWMASK ('M'))) > 0) - fprintf (st, "(undefined) %04o", h->ir); - if (h->ir < 04000) fprintf (st, " [%04o]", h->opnd); - fputc ('\n', st); /* end line */ - } /* end else instruction */ - } /* end for */ +for (k = 0; k < lnt; k++) { /* print specified */ + h = &hst[(++di) % hst_lnt]; /* entry pointer */ + if (h->pc & HIST_PC) { /* instruction? */ + l = (h->lac >> 12) & 1; /* link */ + fprintf (st, "%05o %o %04o %04o ", h->pc & ADDRMASK, l, h->lac & 07777, h->mq); + if (h->ir < 06000) fprintf (st, "%05o ", h->ea); + else fprintf (st, " "); + sim_eval = h->ir; + if ((fprint_sym (st, h->pc & ADDRMASK, &sim_eval, &cpu_unit, SWMASK ('M'))) > 0) + fprintf (st, "(undefined) %04o", h->ir); + if (h->ir < 04000) fprintf (st, " [%04o]", h->opnd); + fputc ('\n', st); /* end line */ + } /* end else instruction */ + } /* end for */ return SCPE_OK; } diff --git a/PDP8/pdp8_defs.h b/PDP8/pdp8_defs.h index 7ac1f8af..0a0ac630 100644 --- a/PDP8/pdp8_defs.h +++ b/PDP8/pdp8_defs.h @@ -1,6 +1,6 @@ /* pdp8_defs.h: PDP-8 simulator definitions - Copyright (c) 1993-2004, Robert M Supnik + Copyright (c) 1993-2005, 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"), @@ -19,101 +19,102 @@ 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 + 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. - 13-Oct-03 RMS Added TSC8-75 support - 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 + 13-Oct-03 RMS Added TSC8-75 support + 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 */ +#ifndef _PDP8_DEFS_H_ +#define _PDP8_DEFS_H_ 0 + +#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 */ -#define STOP_DTOFF 5 /* DECtape off reel */ +#define STOP_RSRV 1 /* must be 1 */ +#define STOP_HALT 2 /* HALT */ +#define STOP_IBKPT 3 /* breakpoint */ +#define STOP_NOTSTD 4 /* non-std devno */ +#define STOP_DTOFF 5 /* DECtape off reel */ /* 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) +#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 */ +#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 */ +#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 */ +#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; +typedef struct { + uint32 dev; /* base dev number */ + uint32 num; /* number of slots */ + int32 (*dsp[DEV_MAXBLK])(int32 IR, int32 dat); + } 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_TSC 036 -#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 */ -#define DEV_TD8E 077 /* TD8E */ - +#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_TSC 036 +#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 */ +#define DEV_TD8E 077 /* TD8E */ + /* 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. + 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. + 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. + 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. @@ -122,73 +123,75 @@ typedef struct pdp8_dib DIB; 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_TSC (INT_V_DIRECT+9) /* TSC8-75 int */ -#define INT_V_OVHD (INT_V_DIRECT+10) /* 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_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_TSC (INT_V_DIRECT+9) /* TSC8-75 int */ +#define INT_V_OVHD (INT_V_DIRECT+10) /* 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_TSC (1 << INT_V_TSC) +#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_TSC (1 << INT_V_TSC) #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)) +#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); + +#endif diff --git a/PDP8/pdp8_df.c b/PDP8/pdp8_df.c index fca3496d..6dac834d 100644 --- a/PDP8/pdp8_df.c +++ b/PDP8/pdp8_df.c @@ -1,6 +1,6 @@ /* pdp8_df.c: DF32 fixed head disk simulator - Copyright (c) 1993-2004, Robert M Supnik + Copyright (c) 1993-2005, 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"), @@ -19,90 +19,90 @@ 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 + 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 + df DF32 fixed head disk - 04-Jan-04 RMS Changed sim_fsize calling sequence - 26-Oct-03 RMS Cleaned up buffer copy code - 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 + 04-Jan-04 RMS Changed sim_fsize calling sequence + 26-Oct-03 RMS Cleaned up buffer copy code + 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 + 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) +#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 */ +#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 */ +#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 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 -#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 */ +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); @@ -117,49 +117,53 @@ 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 + 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) }; +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 } }; + { 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 } }; + { 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 }; - + "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) @@ -167,30 +171,32 @@ 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 */ +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 + 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) @@ -198,14 +204,15 @@ 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; +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 */ + df_sta = df_sta | (AC & (DFS_DEX | DFS_MEX)); /* DEAL */ + AC = AC | old_df_sta; /* DEAC */ + } return AC; } @@ -213,16 +220,18 @@ 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 */ +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 @@ -235,77 +244,85 @@ int32 pa, t, mex; uint32 da; int16 *fbuf = uptr->filebuf; -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); } +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)) M[pa] = fbuf[da]; } /* if !nxm, read wd */ - else { /* write */ - t = (da >> 14) & 07; /* check wr lock */ - if ((df_wlk >> t) & 1) /* locked? set err */ - df_sta = df_sta | DFS_WLS; - else { /* not locked */ - fbuf[da] = M[pa]; /* write word */ - 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 */ +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)) M[pa] = fbuf[da]; /* if !nxm, read wd */ + } + else { /* write */ + t = (da >> 14) & 07; /* check wr lock */ + if ((df_wlk >> t) & 1) /* locked? set err */ + df_sta = df_sta | DFS_WLS; + else { /* not locked */ + fbuf[da] = M[pa]; /* write word */ + 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 */ +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 */ +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 */ +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)) +#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 */ -}; + 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 */ -}; + 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) { @@ -313,12 +330,15 @@ 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; } + 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; } @@ -333,10 +353,11 @@ t_stat r; r = attach_unit (uptr, cptr); if (r != SCPE_OK) return r; if ((uptr->flags & UNIT_AUTO) && (sz = sim_fsize (uptr->fileref))) { - 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); } + 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 SCPE_OK; } diff --git a/PDP8/pdp8_doc.txt b/PDP8/pdp8_doc.txt index 276af796..80219dd0 100644 --- a/PDP8/pdp8_doc.txt +++ b/PDP8/pdp8_doc.txt @@ -1,7 +1,7 @@ To: Users From: Bob Supnik Subj: PDP-8 Simulator Usage -Date: 15-Feb-2005 +Date: 01-Jul-2005 COPYRIGHT NOTICE @@ -27,8 +27,8 @@ The following copyright notice applies to both the SIMH source and binary: 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 + 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. @@ -401,8 +401,7 @@ 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. +active connections. The SET TTIXn DISCONNECT command disconnects line n. The input device (TTIX) implements these registers: diff --git a/PDP8/pdp8_dt.c b/PDP8/pdp8_dt.c index a8e55636..1fd97610 100644 --- a/PDP8/pdp8_dt.c +++ b/PDP8/pdp8_dt.c @@ -1,6 +1,6 @@ /* pdp8_dt.c: PDP-8 DECtape simulator - Copyright (c) 1993-2004, Robert M Supnik + Copyright (c) 1993-2005, 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"), @@ -19,38 +19,39 @@ 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 + 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 + dt TC08/TU56 DECtape - 25-Jan-04 RMS Revised for device debug support - 09-Jan-04 RMS Changed sim_fsize calling sequence, added STOP_OFFR - 18-Oct-03 RMS Fixed bugs in read all, tightened timing - 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 + 16-Aug-05 RMS Fixed C++ declaration and cast problems + 25-Jan-04 RMS Revised for device debug support + 09-Jan-04 RMS Changed sim_fsize calling sequence, added STOP_OFFR + 18-Oct-03 RMS Fixed bugs in read all, tightened timing + 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] + 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. @@ -58,13 +59,13 @@ Tape density is nominally 300 lines per inch. The format of a DECtape (as taken from the TD8E formatter) is: - reverse end zone 8192 reverse end zone codes ~ 10 feet - reverse buffer 200 interblock codes - block 0 - : - block n - forward buffer 200 interblock codes - forward end zone 8192 forward end zone codes ~ 10 feet + reverse end zone 8192 reverse end zone codes ~ 10 feet + reverse buffer 200 interblock codes + block 0 + : + block n + forward buffer 200 interblock codes + forward end zone 8192 forward end zone codes ~ 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 @@ -76,15 +77,15 @@ 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 checksum (for reverse reads) - : - trailer word 4 checksum (for forward reads) - trailer words 3,2 0 - trailer word 1 block number (for reverse reads) - trailer word 0 0 + header word 0 0 + header word 1 block number (for forward reads) + header words 2,3 0 + header word 4 checksum (for reverse reads) + : + trailer word 4 checksum (for forward reads) + 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 non-data words in the bit bucket. @@ -92,183 +93,183 @@ #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 */ +#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_LPERMC 6 /* lines per mark track */ -#define DT_BLKWD 1 /* blk no word in h/t */ -#define DT_CSMWD 4 /* checksum word in h/t */ -#define DT_HTWRD 5 /* header/trailer words */ -#define DT_EZLIN (8192 * DT_LPERMC) /* end zone length */ -#define DT_BFLIN (200 * DT_LPERMC) /* buffer length */ -#define DT_BLKLN (DT_BLKWD * DT_LPERMC) /* blk no line in h/t */ -#define DT_CSMLN (DT_CSMWD * DT_LPERMC) /* csum line in h/t */ -#define DT_HTLIN (DT_HTWRD * DT_LPERMC) /* header/trailer lines */ +#define DT_LPERMC 6 /* lines per mark track */ +#define DT_BLKWD 1 /* blk no word in h/t */ +#define DT_CSMWD 4 /* checksum word in h/t */ +#define DT_HTWRD 5 /* header/trailer words */ +#define DT_EZLIN (8192 * DT_LPERMC) /* end zone length */ +#define DT_BFLIN (200 * DT_LPERMC) /* buffer length */ +#define DT_BLKLN (DT_BLKWD * DT_LPERMC) /* blk no line in h/t */ +#define DT_CSMLN (DT_CSMWD * DT_LPERMC) /* csum line in h/t */ +#define DT_HTLIN (DT_HTWRD * DT_LPERMC) /* header/trailer lines */ /* 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_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)) +#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)) +#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 +#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 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)) +#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_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) +#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)) +#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_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) + ((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) + ((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 */ +#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_BL 004 /* block # lblk */ +#define LOG_MS 001 /* move, search */ +#define LOG_RW 002 /* read, write */ +#define LOG_BL 004 /* 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)) -#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; extern FILE *sim_deb; -int32 dtsa = 0; /* status A */ -int32 dtsb = 0; /* status B */ -int32 dt_ltime = 12; /* interline time */ -int32 dt_dctime = 40000; /* decel time */ +int32 dtsa = 0; /* status A */ +int32 dtsb = 0; /* status B */ +int32 dt_ltime = 12; /* interline time */ +int32 dt_dctime = 40000; /* decel time */ int32 dt_substate = 0; int32 dt_logblk = 0; int32 dt_stopoffr = 0; @@ -294,79 +295,84 @@ 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 + 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) } }; + { 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 | PV_LEFT }, - { DRDATA (DCTIME, dt_dctime, 31), REG_NZ | PV_LEFT }, - { ORDATA (SUBSTATE, dt_substate, 2) }, - { 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) }, - { FLDATA (STOP_OFFR, dt_stopoffr, 0) }, - { ORDATA (DEVNUM, dt_dib.dev, 6), REG_HRO }, - { NULL } }; + { 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 | PV_LEFT }, + { DRDATA (DCTIME, dt_dctime, 31), REG_NZ | PV_LEFT }, + { ORDATA (SUBSTATE, dt_substate, 2) }, + { 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) }, + { FLDATA (STOP_OFFR, dt_stopoffr, 0) }, + { 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 } }; + { 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 } + }; DEBTAB dt_deb[] = { - { "MOTION", LOG_MS }, - { "DATA", LOG_RW }, - { "BLOCK", LOG_BL }, - { NULL, 0 } }; + { "MOTION", LOG_MS }, + { "DATA", LOG_RW }, + { "BLOCK", LOG_BL }, + { 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 | DEV_DEBUG, 0, - dt_deb, NULL, NULL }; - + "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 | DEV_DEBUG, 0, + dt_deb, NULL, NULL + }; + /* IOT routines */ int32 dt76 (int32 IR, int32 AC) @@ -375,24 +381,26 @@ 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; } +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; } @@ -400,15 +408,16 @@ 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 */ +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) @@ -417,31 +426,32 @@ 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; } +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 + - schedule acceleration + - set function as next state 2. If change in motion, start to stop - - if not already decelerating (could be reversing), - schedule deceleration + - 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 + - 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 + - schedule acceleration + - set function as next state 5. If not yet at speed, - - set function as next state + - set function as next state 6. If at speed, - - set function as current state, schedule function + - set function as current state, schedule function */ void dt_newsa (int32 newf) @@ -450,62 +460,70 @@ 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 */ +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 ((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 ((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_dctime - (dt_dctime >> 2)); /* schedule acc */ - DTS_SETSTA (DTS_ACCF | new_dir, 0); /* state = accel */ - DTS_SET2ND (DTS_ATSF | new_dir, new_fnc); /* next = fnc */ - return; } +if (new_mving & ~prev_mving) { /* start? */ + if (dt_setpos (uptr)) return; /* update pos */ + sim_cancel (uptr); /* stop current */ + sim_activate (uptr, dt_dctime - (dt_dctime >> 2)); /* schedule acc */ + 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_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_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_dctime - (dt_dctime >> 2)); /* sched 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_ACCF) { /* not accel/at speed? */ + if (dt_setpos (uptr)) return; /* update pos */ + sim_cancel (uptr); /* cancel cur */ + sim_activate (uptr, dt_dctime - (dt_dctime >> 2)); /* sched 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; } +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; +return; } - + /* Schedule new DECtape function This routine is only called if @@ -523,77 +541,87 @@ 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 */ +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); +unum = (int32) (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 (DEBUG_PRI (dt_dev, LOG_MS)) fprintf (sim_deb, ">>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 (DEBUG_PRI (dt_dev, LOG_MS)) fprintf (sim_deb, ">>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; } +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 (DEBUG_PRI (dt_dev, LOG_MS)) fprintf (sim_deb, ">>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 (DEBUG_PRI (dt_dev, LOG_MS)) fprintf (sim_deb, ">>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) + 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) + 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. @@ -605,40 +633,47 @@ 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_dctime - (dt_dctime >> 2)) / 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 */ +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_dctime - (dt_dctime >> 2)) / 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? */ + 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; } + unum = (int32) (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 @@ -649,7 +684,7 @@ t_stat dt_svc (UNIT *uptr) int32 mot = DTS_GETMOT (uptr->STATE); int32 dir = mot & DTS_DIR; int32 fnc = DTS_GETFNC (uptr->STATE); -int16 *fbuf = uptr->filebuf; +int16 *fbuf = (int16 *) uptr->filebuf; int32 unum = uptr - dt_dev.units; int32 blk, wrd, ma, relpos, dat; uint32 ba; @@ -662,21 +697,26 @@ uint32 ba; */ switch (mot) { -case DTS_DECF: case DTS_DECR: /* decelerating */ - if (dt_setpos (uptr)) /* upd pos; off reel? */ - return IORETURN (dt_stopoffr, STOP_DTOFF); - uptr->STATE = DTS_NXTSTA (uptr->STATE); /* advance state */ - if (uptr->STATE) /* not stopped? */ - sim_activate (uptr, dt_dctime - (dt_dctime >> 2)); /* 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; } + + case DTS_DECF: case DTS_DECR: /* decelerating */ + if (dt_setpos (uptr)) /* upd pos; off reel? */ + return IORETURN (dt_stopoffr, STOP_DTOFF); + uptr->STATE = DTS_NXTSTA (uptr->STATE); /* advance state */ + if (uptr->STATE) /* not stopped? */ + sim_activate (uptr, dt_dctime - (dt_dctime >> 2)); /* 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 @@ -685,270 +725,305 @@ default: /* other */ Off reel - detach unit (it must be deselected) */ -if (dt_setpos (uptr)) /* upd pos; off reel? */ - return IORETURN (dt_stopoffr, STOP_DTOFF); -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; - +if (dt_setpos (uptr)) /* upd pos; off reel? */ + return IORETURN (dt_stopoffr, STOP_DTOFF); +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 + 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 + 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 + 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 (DEBUG_PRI (dt_dev, LOG_RW) || - (DEBUG_PRI (dt_dev, LOG_BL) && (blk == dt_logblk))) - fprintf (sim_deb, ">>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 = fbuf[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; - + 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 (DEBUG_PRI (dt_dev, LOG_RW) || + (DEBUG_PRI (dt_dev, LOG_BL) && (blk == dt_logblk))) + fprintf (sim_deb, ">>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 = fbuf[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 + 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 + 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 (DEBUG_PRI (dt_dev, LOG_RW) || - (DEBUG_PRI (dt_dev, LOG_BL) && (blk == dt_logblk))) - fprintf (sim_deb, ">>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 */ - fbuf[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; - + 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 (DEBUG_PRI (dt_dev, LOG_RW) || + (DEBUG_PRI (dt_dev, LOG_BL) && (blk == dt_logblk))) + fprintf (sim_deb, ">>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 */ + fbuf[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 + 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 = fbuf[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; + 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 = fbuf[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 + 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; - fbuf[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 */ + 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; + fbuf[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) + Forward Reverse + Word Word Content Word Word Content + (abs) (rel) (abs) (rel) - 137 8 fwd csm'00 6 6 rev 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 rev csm 136 7 00'fwd csm + 137 8 fwd csm'00 6 6 rev 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 rev csm 136 7 00'fwd 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: /* rev csm */ - return 077; - 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); - case 7: /* fwd csum */ - return (dt_comobv (dt_csum (uptr, blk)) << 6); - default: /* others */ - return 07777; } } -else { /* forward */ - switch (relpos / DT_WSIZE) { - case 8: /* fwd 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); - case 7: /* rev csum */ - return 077; - default: /* others */ - break; } } +if (dir) { /* reverse */ + switch (relpos / DT_WSIZE) { + case 6: /* rev csm */ + return 077; + 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); + case 7: /* fwd csum */ + return (dt_comobv (dt_csum (uptr, blk)) << 6); + default: /* others */ + return 07777; + } + } +else { /* forward */ + switch (relpos / DT_WSIZE) { + case 8: /* fwd 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); + case 7: /* rev csum */ + return 077; + default: /* others */ + break; + } + } return 0; } - + /* Utility routines */ /* Set error flag */ @@ -957,13 +1032,14 @@ 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 */ +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; } @@ -974,8 +1050,8 @@ 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 */ +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; } @@ -984,9 +1060,9 @@ return; int32 dt_comobv (int32 dat) { -dat = dat ^ 07777; /* compl obverse */ +dat = dat ^ 07777; /* compl obverse */ dat = ((dat >> 9) & 07) | ((dat >> 3) & 070) | - ((dat & 070) << 3) | ((dat & 07) << 9); + ((dat & 070) << 3) | ((dat & 07) << 9); return dat; } @@ -994,17 +1070,18 @@ return dat; int32 dt_csum (UNIT *uptr, int32 blk) { -int16 *fbuf = uptr->filebuf; +int16 *fbuf = (int16 *) 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 = fbuf[ba + i] ^ 07777; /* get ~word */ - csum = csum ^ (wrd >> 6) ^ wrd; } +csum = 077; /* init csum */ +for (i = 0; i < DTU_BSIZE (uptr); i++) { /* loop thru buf */ + wrd = fbuf[ba + i] ^ 07777; /* get ~word */ + csum = csum ^ (wrd >> 6) ^ wrd; + } return (csum & 077); } - + /* Reset routine */ t_stat dt_reset (DEVICE *dptr) @@ -1012,22 +1089,25 @@ 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 */ +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; } @@ -1038,44 +1118,44 @@ return SCPE_OK; doesn't work with the disk monitor. */ -#define BOOT_START 0200 -#define BOOT_LEN (sizeof (boot_rom) / sizeof (int16)) +#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 */ -}; + 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 */ +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 @@ -1093,53 +1173,59 @@ 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 (uptr->fileref))) { - 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; } -fbuf = uptr->filebuf; /* file buffer */ +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 (uptr->fileref))) { + 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 (uint16)); +if (uptr->filebuf == NULL) { /* can't alloc? */ + detach_unit (uptr); + return SCPE_MEM; + } +fbuf = (uint16 *) 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 */ - fbuf[ba] = (pdp18b[k] >> 6) & 07777; - fbuf[ba + 1] = ((pdp18b[k] & 077) << 6) | - ((pdp18b[k + 1] >> 12) & 077); - fbuf[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 */ +if (uptr->flags & UNIT_8FMT) /* 12b? */ + uptr->hwmark = fxread (uptr->filebuf, sizeof (uint16), + 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 (uint16), D18_NBSIZE, uptr->fileref); + for (i = 0; i < k; i++) pdp18b[i] = pdp11b[i]; + } + else k = fxread (pdp18b, sizeof (uint32), 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 */ + fbuf[ba] = (pdp18b[k] >> 6) & 07777; + fbuf[ba + 1] = ((pdp18b[k] & 077) << 6) | + ((pdp18b[k + 1] >> 12) & 077); + fbuf[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; } @@ -1159,42 +1245,46 @@ int32 i, k; int32 u = uptr - dt_dev.units; uint32 ba; -if (!(uptr->flags & UNIT_ATT)) return SCPE_OK; /* attached? */ +if (!(uptr->flags & UNIT_ATT)) return SCPE_OK; /* attached? */ 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; } -fbuf = 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) (fbuf[ba] & 07777) << 6) | - ((uint32) (fbuf[ba + 1] >> 6) & 077); - pdp18b[k + 1] = ((uint32) (fbuf[ba + 1] & 077) << 12) | - ((uint32) (fbuf[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 */ + 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; + } +fbuf = (uint16 *) 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 (uint16), /* 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) (fbuf[ba] & 07777) << 6) | + ((uint32) (fbuf[ba + 1] >> 6) & 077); + pdp18b[k + 1] = ((uint32) (fbuf[ba + 1] & 077) << 12) | + ((uint32) (fbuf[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 (uint16), + D18_NBSIZE, uptr->fileref); + } + else fxwrite (pdp18b, sizeof (uint32), + 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 index 5b4fcfce..d41e30ac 100644 --- a/PDP8/pdp8_lp.c +++ b/PDP8/pdp8_lp.c @@ -1,6 +1,6 @@ /* pdp8_lp.c: PDP-8 line printer simulator - Copyright (c) 1993-2004, Robert M Supnik + Copyright (c) 1993-2005, 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"), @@ -19,23 +19,23 @@ 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 + 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 + 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 + 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 */ +int32 lpt_err = 0; /* error flag */ +int32 lpt_stopioe = 0; /* stop on error */ DEVICE lpt_dev; int32 lpt (int32 IR, int32 AC); @@ -46,88 +46,104 @@ t_stat lpt_detach (UNIT *uptr); /* LPT data structures - lpt_dev LPT device descriptor - lpt_unit LPT unit descriptor - lpt_reg LPT register list + 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 }; + 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 } }; + { 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 } }; + { 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 }; - + "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 */ +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 */ +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); } + 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; } + perror ("LPT I/O error"); + clearerr (lpt_unit.fileref); + return SCPE_IOERR; + } lpt_unit.pos = lpt_unit.pos + 1; return SCPE_OK; } @@ -137,11 +153,11 @@ return SCPE_OK; t_stat lpt_reset (DEVICE *dptr) { lpt_unit.buf = 0; -dev_done = dev_done & ~INT_LPT; /* clear done, int */ +dev_done = dev_done & ~INT_LPT; /* clear done, int */ int_req = int_req & ~INT_LPT; -int_enable = int_enable | INT_LPT; /* set enable */ +int_enable = int_enable | INT_LPT; /* set enable */ lpt_err = (lpt_unit.flags & UNIT_ATT) == 0; -sim_cancel (&lpt_unit); /* deactivate unit */ +sim_cancel (&lpt_unit); /* deactivate unit */ return SCPE_OK; } diff --git a/PDP8/pdp8_mt.c b/PDP8/pdp8_mt.c index b68387e4..9a9313e2 100644 --- a/PDP8/pdp8_mt.c +++ b/PDP8/pdp8_mt.c @@ -19,42 +19,43 @@ 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 + 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 + mt TM8E/TU10 magtape - 18-Mar-05 RMS Added attached test to detach routine - 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 + 16-Aug-05 RMS Fixed C++ declaration and cast problems + 18-Mar-05 RMS Added attached test to detach routine + 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 + 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. @@ -63,85 +64,85 @@ #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) +#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)) +#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) +#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_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 */ -#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 */ +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); @@ -160,58 +161,62 @@ 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 + 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) } }; + { 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 } }; + { 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 } }; + { 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 }; - + "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) @@ -219,113 +224,141 @@ 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 */ +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 */ +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 */ +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 @@ -339,107 +372,115 @@ 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 */ +u = (int32) (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->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); } +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 */ +switch (f) { /* case on function */ -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_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_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; -case FN_WREOF: - if (st = sim_tape_wrtmk (uptr)) /* write tmk, err? */ - r = mt_map_err (uptr, st); /* map error */ - break; + 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_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 */ + 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 */ +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) @@ -458,23 +499,25 @@ 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; } +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 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 */ +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; } @@ -482,8 +525,8 @@ return v; void mt_set_done (void) { -mt_done = 1; /* set done */ -mt_fn = mt_fn & ~(FN_CRC | FN_GO | FN_INC); /* clear func<4:6> */ +mt_done = 1; /* set done */ +mt_fn = mt_fn & ~(FN_CRC | FN_GO | FN_INC); /* clear func<4:6> */ return; } @@ -492,36 +535,45 @@ return; 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; } + + 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) @@ -530,16 +582,17 @@ 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)); +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 = (uint8 *) calloc (MT_MAXFR, sizeof (uint8)); if (mtxb == NULL) return SCPE_MEM; return SCPE_OK; } @@ -549,7 +602,7 @@ return SCPE_OK; t_stat mt_attach (UNIT *uptr, char *cptr) { t_stat r; -int32 u = uptr - mt_dev.units; /* get unit number */ +int32 u = uptr - mt_dev.units; /* get unit number */ r = sim_tape_attach (uptr, cptr); if (r != SCPE_OK) return r; @@ -562,9 +615,9 @@ return r; t_stat mt_detach (UNIT* uptr) { -int32 u = uptr - mt_dev.units; /* get unit number */ +int32 u = uptr - mt_dev.units; /* get unit number */ -if (!(uptr->flags & UNIT_ATT)) return SCPE_OK; /* check for attached */ +if (!(uptr->flags & UNIT_ATT)) return SCPE_OK; /* check for attached */ if (!sim_is_active (uptr)) uptr->USTAT = STA_REM; if (u == GET_UNIT (mt_cu)) mt_updcsta (uptr); return sim_tape_detach (uptr); @@ -574,10 +627,10 @@ return sim_tape_detach (uptr); t_stat mt_vlock (UNIT *uptr, int32 val, char *cptr, void *desc) { -int32 u = uptr - mt_dev.units; /* get unit number */ +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; + 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 index 9c4a11fb..787ba31f 100644 --- a/PDP8/pdp8_pt.c +++ b/PDP8/pdp8_pt.c @@ -1,6 +1,6 @@ /* pdp8_pt.c: PDP-8 paper tape reader/punch simulator - Copyright (c) 1993-2004, Robert M Supnik + Copyright (c) 1993-2005, 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"), @@ -19,24 +19,24 @@ 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 + 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 + 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 + 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_stopioe = 0, ptp_stopioe = 0; /* stop on error */ int32 ptr (int32 IR, int32 AC); int32 ptp (int32 IR, int32 AC); @@ -45,98 +45,111 @@ 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 + 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 }; + 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 } }; + { 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 } }; + { 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 }; + "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 + 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 }; + 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 } }; + { 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 } }; + { 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 }; - + "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 */ +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 */ @@ -145,17 +158,19 @@ t_stat ptr_svc (UNIT *uptr) { int32 temp; -if ((ptr_unit.flags & UNIT_ATT) == 0) /* attached? */ - return IORETURN (ptr_stopioe, SCPE_UNATT); +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 */ + 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; @@ -166,51 +181,58 @@ return SCPE_OK; t_stat ptr_reset (DEVICE *dptr) { ptr_unit.buf = 0; -dev_done = dev_done & ~INT_PTR; /* clear done, int */ +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 */ +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 */ +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); +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; } + perror ("PTP I/O error"); + clearerr (ptp_unit.fileref); + return SCPE_IOERR; + } ptp_unit.pos = ptp_unit.pos + 1; return SCPE_OK; } @@ -220,10 +242,10 @@ return SCPE_OK; t_stat ptp_reset (DEVICE *dptr) { ptp_unit.buf = 0; -dev_done = dev_done & ~INT_PTP; /* clear done, int */ +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 */ +int_enable = int_enable | INT_PTP; /* set enable */ +sim_cancel (&ptp_unit); /* deactivate unit */ return SCPE_OK; } @@ -233,25 +255,25 @@ return SCPE_OK; #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 */ -}; + 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) { @@ -259,7 +281,7 @@ int32 i; extern int32 saved_PC; extern uint16 M[]; -if (ptr_dib.dev != DEV_PTR) return STOP_NOTSTD; /* only std devno */ +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 index b0704bde..ffaeaeef 100644 --- a/PDP8/pdp8_rf.c +++ b/PDP8/pdp8_rf.c @@ -1,6 +1,6 @@ /* pdp8_rf.c: RF08 fixed head disk simulator - Copyright (c) 1993-2004, Robert M Supnik + Copyright (c) 1993-2005, 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"), @@ -19,99 +19,99 @@ 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 + 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 + rf RF08 fixed head disk - 04-Jan-04 RMS Changed sim_fsize calling sequence - 26-Oct-03 RMS Cleaned up buffer copy code - 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 + 04-Jan-04 RMS Changed sim_fsize calling sequence + 26-Oct-03 RMS Cleaned up buffer copy code + 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 + 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) +#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 */ +#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 */ +#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 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 -#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 */ +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); @@ -127,52 +127,56 @@ 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 + 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 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 } }; + { 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 } }; + { 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 }; - + "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) @@ -180,19 +184,21 @@ 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 */ +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; } @@ -200,41 +206,47 @@ 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> */ +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 */ +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; } @@ -242,31 +254,37 @@ 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 */ +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 = 0; /* clear AC */ + break; + + case 5: /* DXAC */ + AC = 0; /* 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 @@ -278,37 +296,45 @@ t_stat rf_svc (UNIT *uptr) int32 pa, t, mex; int16 *fbuf = uptr->filebuf; -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); } +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)) /* if !nxm */ - M[pa] = fbuf[rf_da]; } /* read word */ - else { /* write */ - t = ((rf_da >> 15) & 030) | ((rf_da >> 14) & 07); - if ((rf_wlk >> t) & 1) /* write locked? */ - rf_sta = rf_sta | RFS_WLS; - else { /* not locked */ - fbuf[rf_da] = M[pa]; /* write word */ - 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 */ +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)) /* if !nxm */ + M[pa] = fbuf[rf_da]; /* read word */ + } + else { /* write */ + t = ((rf_da >> 15) & 030) | ((rf_da >> 14) & 07); + if ((rf_wlk >> t) & 1) /* write locked? */ + rf_sta = rf_sta | RFS_WLS; + else { /* not locked */ + fbuf[rf_da] = M[pa]; /* write word */ + 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 */ +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; } @@ -316,20 +342,21 @@ return SCPE_OK; 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; } +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 */ +int_req = int_req & ~INT_RF; /* clear interrupt */ sim_cancel (&rf_unit); sim_cancel (&pcell_unit); return SCPE_OK; @@ -337,42 +364,45 @@ 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)) +#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 */ -}; + 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 */ -}; + 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 (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; } + 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; } @@ -387,10 +417,11 @@ t_stat r; r = attach_unit (uptr, cptr); if (r != SCPE_OK) return r; if ((uptr->flags & UNIT_AUTO) && (sz = sim_fsize (uptr->fileref))) { - 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); } + 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 SCPE_OK; } diff --git a/PDP8/pdp8_rk.c b/PDP8/pdp8_rk.c index 6c4e5d78..d22894a6 100644 --- a/PDP8/pdp8_rk.c +++ b/PDP8/pdp8_rk.c @@ -1,6 +1,6 @@ /* pdp8_rk.c: RK8E cartridge disk simulator - Copyright (c) 1993-2004, Robert M Supnik + Copyright (c) 1993-2005, 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"), @@ -19,121 +19,121 @@ 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 + 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 + 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 + 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 +#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 */ +#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 */ +#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) +#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 /* set done 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 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 /* set done 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)) +#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) +#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 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 + 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 */ +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); @@ -144,51 +144,55 @@ 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 + 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) } }; + { 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 } }; + { 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 } }; + { 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 }; - + "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) @@ -196,57 +200,73 @@ 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 */ +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 @@ -261,33 +281,40 @@ void rk_go (int32 func, int32 cyl) int32 t; UNIT *uptr; -if (func == RKC_RALL) func = RKC_READ; /* all? use standard */ +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; } +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 */ + 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 @@ -305,64 +332,74 @@ 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->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->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; } + 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 */ +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 */ +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 */ +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); } } + 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); } } +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_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; } + perror ("RK I/O error"); + clearerr (uptr->fileref); + return SCPE_IOERR; + } return SCPE_OK; } - + /* Reset routine */ t_stat rk_reset (DEVICE *dptr) @@ -371,12 +408,13 @@ 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; } +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; } @@ -387,22 +425,22 @@ return SCPE_OK; #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> */ -}; + 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 */ +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; diff --git a/PDP8/pdp8_rl.c b/PDP8/pdp8_rl.c index 67f8cda3..56b5f398 100644 --- a/PDP8/pdp8_rl.c +++ b/PDP8/pdp8_rl.c @@ -1,6 +1,6 @@ - /* pdp8_rl.c: RL8A cartridge disk simulator + /* pdp8_rl.c: RL8A cartridge disk simulator - Copyright (c) 1993-2004, Robert M Supnik + Copyright (c) 1993-2005, 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"), @@ -19,17 +19,18 @@ 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 + 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 + rl RL8A cartridge disk - 04-Jan-04 RMS Changed attach routine to use sim_fsize - 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 + 16-Aug-05 RMS Fixed C++ declaration and cast problems + 04-Jan-04 RMS Changed attach routine to use sim_fsize + 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 @@ -48,128 +49,128 @@ /* 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 */ +#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 */ +#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 */ +#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 */ +#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) +#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) +#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) +#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 +#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 */ - +#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 */ +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); @@ -184,181 +185,210 @@ 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 + 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) } }; + { 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 } }; + { 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 } }; + { 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 */ + "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 routines */ 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 */ +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 */ +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 @@ -374,106 +404,120 @@ 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; } +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 ((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; } + 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_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_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; } } + || (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_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 */ +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 */ +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; } +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) @@ -504,10 +548,11 @@ 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 (uint8)); + uptr = rl_dev.units + i; + sim_cancel (uptr); + uptr->STAT = 0; + } +if (rlxb == NULL) rlxb = (uint8 *) calloc (RL_MAXFR, sizeof (uint8)); if (rlxb == NULL) return SCPE_MEM; return SCPE_OK; } @@ -520,19 +565,23 @@ 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 ((p = sim_fsize (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? */ +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 ((p = sim_fsize (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; } + uptr->flags = uptr->flags | UNIT_RL02; + uptr->capac = RL02_SIZE; + } +else { + uptr->flags = uptr->flags & ~UNIT_RL02; + uptr->capac = RL01_SIZE; + } return SCPE_OK; } @@ -549,16 +598,16 @@ return SCPE_OK; 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 + 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 + uptr = pointer to unit + val = ignored Outputs: - sta = status code + sta = status code */ t_stat rl_set_bad (UNIT *uptr, int32 val, char *cptr, void *desc) @@ -571,48 +620,48 @@ 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); +fxwrite (rlxb, sizeof (uint8), 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_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 */ -}; + 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) @@ -620,8 +669,8 @@ 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 */ +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; diff --git a/PDP8/pdp8_rx.c b/PDP8/pdp8_rx.c index 6cba46c4..b1e6969e 100644 --- a/PDP8/pdp8_rx.c +++ b/PDP8/pdp8_rx.c @@ -1,6 +1,6 @@ /* pdp8_rx.c: RX8E/RX01, RX28/RX02 floppy disk simulator - Copyright (c) 1993-2004, Robert M Supnik + Copyright (c) 1993-2005, 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"), @@ -19,29 +19,29 @@ 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 + 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 + rx RX8E/RX01, RX28/RX02 floppy disk - 04-Jan-04 RMS Changed sim_fsize calling sequence - 05-Nov-03 RMS Fixed bug in RX28 read status (found by Charles Dickman) - 26-Oct-03 RMS Cleaned up buffer copy code, fixed double density write - 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 + 04-Jan-04 RMS Changed sim_fsize calling sequence + 05-Nov-03 RMS Fixed bug in RX28 read status (found by Charles Dickman) + 26-Oct-03 RMS Cleaned up buffer copy code, fixed double density write + 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 @@ -55,84 +55,84 @@ #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 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 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 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 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 -#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 */ -int32 rx_bptr = 0; /* buffer pointer */ +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 */ +int32 rx_bptr = 0; /* buffer pointer */ DEVICE rx_dev; int32 rx (int32 IR, int32 AC); @@ -145,187 +145,215 @@ 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 + 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) } }; + { 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, rx_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 } }; + { 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, rx_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 } }; + { 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 }; - + "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 */ +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 */ + rx_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 */ -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 */ - rx_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 */ +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 */ + rx_esr = rx_esr & RXES_ID; /* clear errors */ + break; + + case RXCS_EMPTY: + rx_state = EMPTY; /* state = empty */ + rx_esr = rx_esr & RXES_ID; /* clear errors */ + 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 */ + rx_esr = rx_esr & RXES_ID; /* clear errors */ + 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 */ -switch (RXCS_GETFNC (rx_csr)) { /* decode command */ -case RXCS_FILL: - rx_state = FILL; /* state = fill */ - rx_tr = 1; /* xfer is ready */ - rx_esr = rx_esr & RXES_ID; /* clear errors */ - break; -case RXCS_EMPTY: - rx_state = EMPTY; /* state = empty */ - rx_esr = rx_esr & RXES_ID; /* clear errors */ - 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 */ - rx_esr = rx_esr & RXES_ID; /* clear errors */ - 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[rx_bptr], advance ptr - if rx_bptr > max, finish command, else set tr - EMPTY if rx_bptr > max, finish command, else - copy rx_buf[rx_bptr] to dbr, advance ptr, set tr - CMD_COMPLETE copy requested data to dbr, finish command + 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[rx_bptr], advance ptr + if rx_bptr > max, finish command, else set tr + EMPTY if rx_bptr > max, finish command, else + copy rx_buf[rx_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; @@ -339,140 +367,165 @@ int8 *fbuf = uptr->filebuf; uint32 da; #define PTR12(x) (((x) + (x) + (x)) >> 1) -if (rx_28 && (uptr->flags & UNIT_DEN)) /* RX28 and double density? */ - bps = RX2_NUMBY; /* double bytes/sector */ -else bps = RX_NUMBY; /* RX8E, normal count */ +if (rx_28 && (uptr->flags & UNIT_DEN)) /* RX28 and double density? */ + bps = RX2_NUMBY; /* double bytes/sector */ +else bps = RX_NUMBY; /* RX8E, normal count */ wps = bps / 2; -func = RXCS_GETFNC (rx_csr); /* get function */ -switch (rx_state) { /* case on state */ +func = RXCS_GETFNC (rx_csr); /* get function */ +switch (rx_state) { /* case on state */ -case IDLE: /* idle */ - return SCPE_IERR; + case IDLE: /* idle */ + return SCPE_IERR; -case EMPTY: /* empty buffer */ - if (rx_csr & RXCS_MODE) { /* 8b xfer? */ - if (rx_bptr >= bps) { /* done? */ - rx_done (0, 0); /* set done */ - break; } /* and exit */ - rx_dbr = rx_buf[rx_bptr]; } /* else get data */ - else { - byptr = PTR12 (rx_bptr); /* 12b xfer */ - if (rx_bptr >= wps) { /* done? */ - rx_done (0, 0); /* set done */ - break; } /* and exit */ - rx_dbr = (rx_bptr & 1)? /* get data */ - ((rx_buf[byptr] & 017) << 8) | rx_buf[byptr + 1]: - (rx_buf[byptr] << 4) | ((rx_buf[byptr + 1] >> 4) & 017); } - rx_bptr = rx_bptr + 1; - rx_tr = 1; - break; + case EMPTY: /* empty buffer */ + if (rx_csr & RXCS_MODE) { /* 8b xfer? */ + if (rx_bptr >= bps) { /* done? */ + rx_done (0, 0); /* set done */ + break; /* and exit */ + } + rx_dbr = rx_buf[rx_bptr]; /* else get data */ + } + else { + byptr = PTR12 (rx_bptr); /* 12b xfer */ + if (rx_bptr >= wps) { /* done? */ + rx_done (0, 0); /* set done */ + break; /* and exit */ + } + rx_dbr = (rx_bptr & 1)? /* get data */ + ((rx_buf[byptr] & 017) << 8) | rx_buf[byptr + 1]: + (rx_buf[byptr] << 4) | ((rx_buf[byptr + 1] >> 4) & 017); + } + rx_bptr = rx_bptr + 1; + rx_tr = 1; + break; -case FILL: /* fill buffer */ - if (rx_csr & RXCS_MODE) { /* 8b xfer? */ - rx_buf[rx_bptr] = rx_dbr; /* fill buffer */ - rx_bptr = rx_bptr + 1; - if (rx_bptr < bps) rx_tr = 1; /* if more, set xfer */ - else rx_done (0, 0); } /* else done */ - else { - byptr = PTR12 (rx_bptr); /* 12b xfer */ - if (rx_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; } - rx_bptr = rx_bptr + 1; - if (rx_bptr < wps) rx_tr = 1; /* if more, set xfer */ - else { - for (i = PTR12 (wps); i < bps; i++) - rx_buf[i] = 0; /* else fill sector */ - rx_done (0, 0); } } /* set done */ - break; + case FILL: /* fill buffer */ + if (rx_csr & RXCS_MODE) { /* 8b xfer? */ + rx_buf[rx_bptr] = rx_dbr; /* fill buffer */ + rx_bptr = rx_bptr + 1; + if (rx_bptr < bps) rx_tr = 1; /* if more, set xfer */ + else rx_done (0, 0); /* else done */ + } + else { + byptr = PTR12 (rx_bptr); /* 12b xfer */ + if (rx_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; + } + rx_bptr = rx_bptr + 1; + if (rx_bptr < wps) rx_tr = 1; /* if more, set xfer */ + else { + for (i = PTR12 (wps); i < bps; 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] = fbuf[da + i]; } - else { /* write */ - if (uptr->flags & UNIT_WPRT) { /* locked? */ - rx_done (0, 0100); /* done, error */ - break; } - for (i = 0; i < bps; i++) fbuf[da + i] = rx_buf[i]; - da = da + bps; - if (da > uptr->hwmark) uptr->hwmark = da; } - rx_done (0, 0); /* 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 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++) fbuf[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 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 CMD_COMPLETE: /* command complete */ - if (func == RXCS_ECODE) { /* read ecode? */ - rx_dbr = rx_ecode; /* set dbr */ - rx_done (0, -1); } /* don't update */ - else if (rx_28) { /* no, read sta; RX28? */ - rx_esr = rx_esr & ~RXES_DERR; /* assume dens match */ - if (((uptr->flags & UNIT_DEN) != 0) ^ /* densities mismatch? */ - ((rx_csr & RXCS_DEN) != 0)) - rx_done (RXES_DERR, 0240); /* yes, error */ - else rx_done (0, 0); } /* no, ok */ - else rx_done (0, 0); /* RX8E status */ - break; + 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] = fbuf[da + i]; + } + else { /* write */ + if (uptr->flags & UNIT_WPRT) { /* locked? */ + rx_done (0, 0100); /* done, error */ + break; + } + for (i = 0; i < bps; i++) fbuf[da + i] = rx_buf[i]; + da = da + bps; + 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++) fbuf[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 if (rx_28) { /* no, read sta; RX28? */ + rx_esr = rx_esr & ~RXES_DERR; /* assume dens match */ + if (((uptr->flags & UNIT_DEN) != 0) ^ /* densities mismatch? */ + ((rx_csr & RXCS_DEN) != 0)) + rx_done (RXES_DERR, 0240); /* yes, error */ + else rx_done (0, 0); /* no, ok */ + } + else rx_done (0, 0); /* RX8E status */ + 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] = fbuf[da + i]; + rx_done (RXES_ID, 0); /* set done */ + if ((rx_unit[1].flags & UNIT_ATT) == 0) rx_ecode = 0020; + break; + } /* end case state */ -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] = fbuf[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. */ @@ -481,19 +534,20 @@ 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_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; /* RX28? */ -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 */ +if (rx_28) rx_esr = rx_esr | RXES_RX02; /* RX28? */ +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; } @@ -502,20 +556,21 @@ return; 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 */ +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 */ +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; } @@ -529,8 +584,9 @@ t_stat r; r = attach_unit (uptr, cptr); if (r != SCPE_OK) return r; if ((uptr->flags & UNIT_AUTO) && (sz = sim_fsize (uptr->fileref))) { - if (sz > RX_SIZE) uptr->flags = uptr->flags | UNIT_DEN; - else uptr->flags = uptr->flags & ~UNIT_DEN; } + 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 SCPE_OK; } @@ -540,7 +596,7 @@ return SCPE_OK; 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 */ +if ((rx_28 == 0) && val) return SCPE_NOFNC; /* not on RX8E */ uptr->capac = val? RX2_SIZE: RX_SIZE; return SCPE_OK; } @@ -554,11 +610,13 @@ 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; } + 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_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; } @@ -571,88 +629,88 @@ 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)) +#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 */ -}; + 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 */ -}; + 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) { @@ -660,13 +718,15 @@ int32 i; extern int32 saved_PC; extern uint16 M[]; -if (rx_dib.dev != DEV_RX) return STOP_NOTSTD; /* only std devno */ +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; } + 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; } + saved_PC = BOOT_ENTRY; + } return SCPE_OK; } diff --git a/PDP8/pdp8_sys.c b/PDP8/pdp8_sys.c index 7949773a..c2a9e1eb 100644 --- a/PDP8/pdp8_sys.c +++ b/PDP8/pdp8_sys.c @@ -1,6 +1,6 @@ /* pdp8_sys.c: PDP-8 simulator interface - Copyright (c) 1993-2004, Robert M Supnik + Copyright (c) 1993-2005, 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"), @@ -19,24 +19,24 @@ 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 + 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-Oct-03 RMS Added TSC8-75, TD8E support, DECtape off reel message - 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 + 17-Oct-03 RMS Added TSC8-75, TD8E support, DECtape off reel message + 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" @@ -60,13 +60,13 @@ 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 + 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"; @@ -76,34 +76,36 @@ REG *sim_PC = &cpu_reg[0]; int32 sim_emax = 4; DEVICE *sim_devices[] = { - &cpu_dev, - &tsc_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, - &td_dev, - &mt_dev, - NULL }; + &cpu_dev, + &tsc_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, + &td_dev, + &mt_dev, + NULL + }; const char *sim_stop_messages[] = { - "Unknown error", - "Unimplemented instruction", - "HALT instruction", - "Breakpoint", - "Non-standard device number", - "DECtape off reel" }; - + "Unknown error", + "Unimplemented instruction", + "HALT instruction", + "Breakpoint", + "Non-standard device number", + "DECtape off reel" + }; + /* Binary loader Two loader formats are supported: RIM loader (-r) and BIN (-b) loader. @@ -124,89 +126,105 @@ 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? */ +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 */ + 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) +#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 }; + 07416, 07571, 017457 + }; static const char *opcode[] = { "SKON", "ION", "IOF", "SRQ", @@ -261,11 +279,12 @@ static const char *opcode[] = { "ACS", "MUY", "DVI", "NMI", "SHL", "ASR", "LSR", "SCA", "DAD", "DST", "SWBA", "DPSZ", "DPIC", "DCIM", "SAM", - "CLA", "CLL", "CMA", "CML", "IAC", /* encode only */ + "CLA", "CLL", "CMA", "CML", "IAC", /* encode only */ "CLA", "OAS", "HLT", "CLA", "MQA", "MQL", - NULL, NULL, NULL, NULL, /* decode only */ - NULL }; + NULL, NULL, NULL, NULL, /* decode only */ + NULL + }; static const int32 opc_val[] = { 06000+I_NPN, 06001+I_NPN, 06002+I_NPN, 06003+I_NPN, @@ -328,42 +347,45 @@ static const int32 opc_val[] = { 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 }; - + -1 + }; + /* Operate decode Inputs: - *of = output stream - inst = mask bits - class = instruction class code - sp = space needed? + *of = output stream + inst = mask bits + class = instruction class code + sp = space needed? Outputs: - status = space needed + 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; } } +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 + *of = output stream + addr = current PC + *val = pointer to data + *uptr = pointer to unit + sw = switches Outputs: - return = status code + return = status code */ #define FMTASC(x) ((x) < 040)? "<%03o>": "%c", (x) @@ -371,79 +393,93 @@ return sp; #define TSSTOASC(x) ((x) + 040) t_stat fprint_sym (FILE *of, t_addr addr, t_value *val, - UNIT *uptr, int32 sw) + 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 ('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? */ +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 */ + 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 + *cptr = pointer to input string + addr = current PC + *uptr = pointer to unit + *val = pointer to output values + sw = switches Outputs: - status = error status + status = error status */ t_stat parse_sym (char *cptr, t_addr addr, UNIT *uptr, t_value *val, int32 sw) @@ -453,80 +489,96 @@ t_stat r; char gbuf[CBUFSIZE]; cflag = (uptr == NULL) || (uptr == &cpu_unit); -while (isspace (*cptr)) cptr++; /* absorb spaces */ +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 (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 (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; } - + 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 */ +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 */ +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? */ +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_td.c b/PDP8/pdp8_td.c index ac188a52..0c43f8c9 100644 --- a/PDP8/pdp8_td.c +++ b/PDP8/pdp8_td.c @@ -1,6 +1,6 @@ /* pdp8_td.c: PDP-8 simple DECtape controller (TD8E) simulator - Copyright (c) 1993-2004, Robert M Supnik + Copyright (c) 1993-2005, 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"), @@ -19,23 +19,24 @@ 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 + 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 was inspired by Gerold Pauler's TD8E simulator for Doug Jones' PDP8 simulator but tracks the hardware implementation more closely. - td TD8E/TU56 DECtape + td TD8E/TU56 DECtape - 09-Jan-04 RMS Changed sim_fsize calling sequence, added STOP_OFFR + 16-Aug-05 RMS Fixed C++ declaration and cast problems + 09-Jan-04 RMS Changed sim_fsize calling sequence, added STOP_OFFR PDP-8 DECtapes are represented in memory by fixed length buffer of 12b 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] + 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/36b DECtape file is read in, it is converted to 12b format. @@ -43,13 +44,13 @@ Tape density is nominally 300 lines per inch. The format of a DECtape (as taken from the TD8E formatter) is: - reverse end zone 8192 reverse end zone codes ~ 10 feet - reverse buffer 200 interblock codes - block 0 - : - block n - forward buffer 200 interblock codes - forward end zone 8192 forward end zone codes ~ 10 feet + reverse end zone 8192 reverse end zone codes ~ 10 feet + reverse buffer 200 interblock codes + block 0 + : + block n + forward buffer 200 interblock codes + forward end zone 8192 forward end zone codes ~ 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 @@ -61,15 +62,15 @@ of non-data words. Read 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 checksum (for reverse reads) - : - trailer word 4 checksum (for forward reads) - trailer words 3,2 0 - trailer word 1 block number (for reverse reads) - trailer word 0 0 + header word 0 0 + header word 1 block number (for forward reads) + header words 2,3 0 + header word 4 checksum (for reverse reads) + : + trailer word 4 checksum (for forward reads) + trailer words 3,2 0 + trailer word 1 block number (for reverse reads) + trailer word 0 0 Write modifies only the data words and dumps the non-data words in the bit bucket. @@ -77,116 +78,116 @@ #include "pdp8_defs.h" -#define DT_NUMDR 2 /* #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 UNIT_WPRT (UNIT_WLK | UNIT_RO) /* write protect */ +#define DT_NUMDR 2 /* #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 UNIT_WPRT (UNIT_WLK | UNIT_RO) /* write protect */ /* System independent DECtape constants */ -#define DT_LPERMC 6 /* lines per mark track */ -#define DT_EZLIN (8192 * DT_LPERMC) /* end zone length */ -#define DT_BFLIN (200 * DT_LPERMC) /* end zone buffer */ -#define DT_HTLIN (5 * DT_LPERMC) /* lines per hdr/trlr */ +#define DT_LPERMC 6 /* lines per mark track */ +#define DT_EZLIN (8192 * DT_LPERMC) /* end zone length */ +#define DT_BFLIN (200 * DT_LPERMC) /* end zone buffer */ +#define DT_HTLIN (5 * DT_LPERMC) /* lines per hdr/trlr */ /* 16b, 18b, 36b DECtape constants */ -#define D18_WSIZE 6 /* word sizein 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_WSIZE 6 /* word sizein 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)) +#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)) +#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 +#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 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_LIN2BL(p,u) (((p) - DT_EZLIN) / DTU_LPERB (u)) +#define DT_LIN2OF(p,u) (((p) - DT_EZLIN) % DTU_LPERB (u)) /* Command register */ -#define TDC_UNIT 04000 /* unit select */ -#define TDC_FWDRV 02000 /* fwd/rev */ -#define TDC_STPGO 01000 /* stop/go */ -#define TDC_RW 00400 /* read/write */ -#define TDC_MASK 07400 /* implemented */ -#define TDC_GETUNIT(x) (((x) & TDC_UNIT)? 1: 0) +#define TDC_UNIT 04000 /* unit select */ +#define TDC_FWDRV 02000 /* fwd/rev */ +#define TDC_STPGO 01000 /* stop/go */ +#define TDC_RW 00400 /* read/write */ +#define TDC_MASK 07400 /* implemented */ +#define TDC_GETUNIT(x) (((x) & TDC_UNIT)? 1: 0) /* Status register */ -#define TDS_WLO 00200 /* write lock */ -#define TDS_TME 00100 /* timing/sel err */ +#define TDS_WLO 00200 /* write lock */ +#define TDS_TME 00100 /* timing/sel err */ /* Mark track register and codes */ -#define MTK_MASK 077 -#define MTK_REV_END 055 /* rev end zone */ -#define MTK_INTER 025 /* interblock */ -#define MTK_FWD_BLK 026 /* fwd block */ -#define MTK_REV_GRD 032 /* reverse guard */ -#define MTK_FWD_PRE 010 /* lock, etc */ -#define MTK_DATA 070 /* data */ -#define MTK_REV_PRE 073 /* lock, etc */ -#define MTK_FWD_GRD 051 /* fwd guard */ -#define MTK_REV_BLK 045 /* rev block */ -#define MTK_FWD_END 022 /* fwd end zone */ +#define MTK_MASK 077 +#define MTK_REV_END 055 /* rev end zone */ +#define MTK_INTER 025 /* interblock */ +#define MTK_FWD_BLK 026 /* fwd block */ +#define MTK_REV_GRD 032 /* reverse guard */ +#define MTK_FWD_PRE 010 /* lock, etc */ +#define MTK_DATA 070 /* data */ +#define MTK_REV_PRE 073 /* lock, etc */ +#define MTK_FWD_GRD 051 /* fwd guard */ +#define MTK_REV_BLK 045 /* rev block */ +#define MTK_FWD_END 022 /* fwd end zone */ /* DECtape state */ -#define STA_STOP 0 /* stopped */ -#define STA_DEC 2 /* decelerating */ -#define STA_ACC 4 /* accelerating */ -#define STA_UTS 6 /* up to speed */ -#define STA_DIR 1 /* fwd/rev */ +#define STA_STOP 0 /* stopped */ +#define STA_DEC 2 /* decelerating */ +#define STA_ACC 4 /* accelerating */ +#define STA_UTS 6 /* up to speed */ +#define STA_DIR 1 /* fwd/rev */ + +#define ABS(x) (((x) < 0)? (-(x)): (x)) +#define MTK_BIT(c,p) (((c) >> (DT_LPERMC - 1 - ((p) % DT_LPERMC))) & 1) -#define ABS(x) (((x) < 0)? (-(x)): (x)) -#define MTK_BIT(c,p) (((c) >> (DT_LPERMC - 1 - ((p) % DT_LPERMC))) & 1) - /* State and declarations */ -int32 td_cmd = 0; /* command */ -int32 td_dat = 0; /* data */ -int32 td_mtk = 0; /* mark track */ -int32 td_slf = 0; /* single line flag */ -int32 td_qlf = 0; /* quad line flag */ -int32 td_tme = 0; /* timing error flag */ -int32 td_csum = 0; /* save check sum */ -int32 td_qlctr = 0; /* quad line ctr */ -int32 td_ltime = 20; /* interline time */ -int32 td_dctime = 40000; /* decel time */ +int32 td_cmd = 0; /* command */ +int32 td_dat = 0; /* data */ +int32 td_mtk = 0; /* mark track */ +int32 td_slf = 0; /* single line flag */ +int32 td_qlf = 0; /* quad line flag */ +int32 td_tme = 0; /* timing error flag */ +int32 td_csum = 0; /* save check sum */ +int32 td_qlctr = 0; /* quad line ctr */ +int32 td_ltime = 20; /* interline time */ +int32 td_dctime = 40000; /* decel time */ int32 td_stopoffr = 0; -static uint8 tdb_mtk[DT_NUMDR][D18_LPERB]; /* mark track bits */ +static uint8 tdb_mtk[DT_NUMDR][D18_LPERB]; /* mark track bits */ DEVICE td_dev; int32 td77 (int32 IR, int32 AC); @@ -210,116 +211,130 @@ extern int32 sim_is_running; /* TD data structures - td_dev DT device descriptor - td_unit DT unit list - td_reg DT register list - td_mod DT modifier list + td_dev DT device descriptor + td_unit DT unit list + td_reg DT register list + td_mod DT modifier list */ DIB td_dib = { DEV_TD8E, 1, { &td77 } }; UNIT td_unit[] = { - { UDATA (&td_svc, UNIT_8FMT+UNIT_FIX+UNIT_ATTABLE+ - UNIT_DISABLE+UNIT_ROABLE, DT_CAPAC) }, - { UDATA (&td_svc, UNIT_8FMT+UNIT_FIX+UNIT_ATTABLE+ - UNIT_DISABLE+UNIT_ROABLE, DT_CAPAC) } }; + { UDATA (&td_svc, UNIT_8FMT+UNIT_FIX+UNIT_ATTABLE+ + UNIT_DISABLE+UNIT_ROABLE, DT_CAPAC) }, + { UDATA (&td_svc, UNIT_8FMT+UNIT_FIX+UNIT_ATTABLE+ + UNIT_DISABLE+UNIT_ROABLE, DT_CAPAC) } + }; REG td_reg[] = { - { GRDATA (TDCMD, td_cmd, 8, 4, 8) }, - { ORDATA (TDDAT, td_dat, 12) }, - { ORDATA (TDMTK, td_mtk, 6) }, - { FLDATA (TDSLF, td_slf, 0) }, - { FLDATA (TDQLF, td_qlf, 0) }, - { FLDATA (TDTME, td_tme, 0) }, - { ORDATA (TDQL, td_qlctr, 2) }, - { ORDATA (TDCSUM, td_csum, 6), REG_RO }, - { DRDATA (LTIME, td_ltime, 31), REG_NZ | PV_LEFT }, - { DRDATA (DCTIME, td_dctime, 31), REG_NZ | PV_LEFT }, - { URDATA (POS, td_unit[0].pos, 10, T_ADDR_W, 0, - DT_NUMDR, PV_LEFT | REG_RO) }, - { URDATA (STATT, td_unit[0].STATE, 8, 18, 0, - DT_NUMDR, REG_RO) }, - { URDATA (LASTT, td_unit[0].LASTT, 10, 32, 0, - DT_NUMDR, REG_HRO) }, - { FLDATA (STOP_OFFR, td_stopoffr, 0) }, - { ORDATA (DEVNUM, td_dib.dev, 6), REG_HRO }, - { NULL } }; + { GRDATA (TDCMD, td_cmd, 8, 4, 8) }, + { ORDATA (TDDAT, td_dat, 12) }, + { ORDATA (TDMTK, td_mtk, 6) }, + { FLDATA (TDSLF, td_slf, 0) }, + { FLDATA (TDQLF, td_qlf, 0) }, + { FLDATA (TDTME, td_tme, 0) }, + { ORDATA (TDQL, td_qlctr, 2) }, + { ORDATA (TDCSUM, td_csum, 6), REG_RO }, + { DRDATA (LTIME, td_ltime, 31), REG_NZ | PV_LEFT }, + { DRDATA (DCTIME, td_dctime, 31), REG_NZ | PV_LEFT }, + { URDATA (POS, td_unit[0].pos, 10, T_ADDR_W, 0, + DT_NUMDR, PV_LEFT | REG_RO) }, + { URDATA (STATT, td_unit[0].STATE, 8, 18, 0, + DT_NUMDR, REG_RO) }, + { URDATA (LASTT, td_unit[0].LASTT, 10, 32, 0, + DT_NUMDR, REG_HRO) }, + { FLDATA (STOP_OFFR, td_stopoffr, 0) }, + { ORDATA (DEVNUM, td_dib.dev, 6), REG_HRO }, + { NULL } + }; MTAB td_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 }, - { MTAB_XTD|MTAB_VUN|MTAB_NMO, 0, "POSITION", NULL, NULL, &td_show_pos }, - { 0 } }; + { 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 }, + { MTAB_XTD|MTAB_VUN|MTAB_NMO, 0, "POSITION", NULL, NULL, &td_show_pos }, + { 0 } + }; DEVICE td_dev = { - "TD", td_unit, td_reg, td_mod, - DT_NUMDR, 8, 24, 1, 8, 12, - NULL, NULL, &td_reset, - &td_boot, &td_attach, &td_detach, - &td_dib, DEV_DISABLE | DEV_DIS }; - + "TD", td_unit, td_reg, td_mod, + DT_NUMDR, 8, 24, 1, 8, 12, + NULL, NULL, &td_reset, + &td_boot, &td_attach, &td_detach, + &td_dib, DEV_DISABLE | DEV_DIS + }; + /* IOT routines */ int32 td77 (int32 IR, int32 AC) { int32 pulse = IR & 07; -int32 u = TDC_GETUNIT (td_cmd); /* get unit */ +int32 u = TDC_GETUNIT (td_cmd); /* get unit */ int32 diff, t; switch (pulse) { -case 01: /* SDSS */ - if (td_slf) return AC | IOT_SKP; - break; -case 02: /* SDST */ - if (td_tme) return AC | IOT_SKP; - break; -case 03: /* SDSQ */ - if (td_qlf) return AC | IOT_SKP; - break; -case 04: /* SDLC */ - td_tme = 0; /* clear tim err */ - diff = (td_cmd ^ AC) & TDC_MASK; /* cmd changes */ - td_cmd = AC & TDC_MASK; /* update cmd */ - if ((diff != 0) && (diff != TDC_RW)) { /* signif change? */ - if (td_newsa (td_cmd)) /* new command */ - return AC | (IORETURN (td_stopoffr, STOP_DTOFF) << IOT_V_REASON); } - break; -case 05: /* SDLD */ - td_slf = 0; /* clear flags */ - td_qlf = 0; - td_qlctr = 0; - td_dat = AC; /* load data reg */ - break; -case 06: /* SDRC */ - td_slf = 0; /* clear flags */ - td_qlf = 0; - td_qlctr = 0; - t = td_cmd | td_mtk; /* form status */ - if (td_tme || !(td_unit[u].flags & UNIT_ATT)) /* tim/sel err? */ - t = t | TDS_TME; - if (td_unit[u].flags & UNIT_WPRT) /* write locked? */ - t = t | TDS_WLO; - return t; /* return status */ -case 07: /* SDRD */ - td_slf = 0; /* clear flags */ - td_qlf = 0; - td_qlctr = 0; - return td_dat; } /* return data */ + + case 01: /* SDSS */ + if (td_slf) return AC | IOT_SKP; + break; + + case 02: /* SDST */ + if (td_tme) return AC | IOT_SKP; + break; + + case 03: /* SDSQ */ + if (td_qlf) return AC | IOT_SKP; + break; + + case 04: /* SDLC */ + td_tme = 0; /* clear tim err */ + diff = (td_cmd ^ AC) & TDC_MASK; /* cmd changes */ + td_cmd = AC & TDC_MASK; /* update cmd */ + if ((diff != 0) && (diff != TDC_RW)) { /* signif change? */ + if (td_newsa (td_cmd)) /* new command */ + return AC | (IORETURN (td_stopoffr, STOP_DTOFF) << IOT_V_REASON); + } + break; + + case 05: /* SDLD */ + td_slf = 0; /* clear flags */ + td_qlf = 0; + td_qlctr = 0; + td_dat = AC; /* load data reg */ + break; + + case 06: /* SDRC */ + td_slf = 0; /* clear flags */ + td_qlf = 0; + td_qlctr = 0; + t = td_cmd | td_mtk; /* form status */ + if (td_tme || !(td_unit[u].flags & UNIT_ATT)) /* tim/sel err? */ + t = t | TDS_TME; + if (td_unit[u].flags & UNIT_WPRT) /* write locked? */ + t = t | TDS_WLO; + return t; /* return status */ + + case 07: /* SDRD */ + td_slf = 0; /* clear flags */ + td_qlf = 0; + td_qlctr = 0; + return td_dat; /* return data */ + } + return AC; } - + /* Command register change (start/stop, forward/reverse, new unit) 1. If change in motion, stop to start - - schedule up to speed - - set function as next state + - schedule up to speed + - set function as next state 2. If change in motion, start to stop, or change in direction - - schedule stop + - schedule stop */ t_bool td_newsa (int32 newf) @@ -327,52 +342,55 @@ t_bool td_newsa (int32 newf) int32 prev_mving, new_mving, prev_dir, new_dir; UNIT *uptr; -uptr = td_dev.units + TDC_GETUNIT (newf); /* new unit */ -if ((uptr->flags & UNIT_ATT) == 0) return FALSE; /* new unit attached? */ +uptr = td_dev.units + TDC_GETUNIT (newf); /* new unit */ +if ((uptr->flags & UNIT_ATT) == 0) return FALSE; /* new unit attached? */ -new_mving = ((newf & TDC_STPGO) != 0); /* new moving? */ -prev_mving = (uptr->STATE != STA_STOP); /* previous moving? */ -new_dir = ((newf & TDC_FWDRV) != 0); /* new dir? */ -prev_dir = ((uptr->STATE & STA_DIR) != 0); /* previous dir? */ +new_mving = ((newf & TDC_STPGO) != 0); /* new moving? */ +prev_mving = (uptr->STATE != STA_STOP); /* previous moving? */ +new_dir = ((newf & TDC_FWDRV) != 0); /* new dir? */ +prev_dir = ((uptr->STATE & STA_DIR) != 0); /* previous dir? */ -td_mtk = 0; /* mark trk reg cleared */ +td_mtk = 0; /* mark trk reg cleared */ -if (!prev_mving && !new_mving) return FALSE; /* stop from stop? */ +if (!prev_mving && !new_mving) return FALSE; /* stop from stop? */ -if (new_mving && !prev_mving) { /* start from stop? */ - if (td_setpos (uptr)) return TRUE; /* update pos */ - sim_cancel (uptr); /* stop current */ - sim_activate (uptr, td_dctime - (td_dctime >> 2)); /* sched accel */ - uptr->STATE = STA_ACC | new_dir; /* set status */ - td_slf = td_qlf = td_qlctr = 0; /* clear state */ - return FALSE; } +if (new_mving && !prev_mving) { /* start from stop? */ + if (td_setpos (uptr)) return TRUE; /* update pos */ + sim_cancel (uptr); /* stop current */ + sim_activate (uptr, td_dctime - (td_dctime >> 2)); /* sched accel */ + uptr->STATE = STA_ACC | new_dir; /* set status */ + td_slf = td_qlf = td_qlctr = 0; /* clear state */ + return FALSE; + } -if ((prev_mving && !new_mving) || /* stop from moving? */ - (prev_dir != new_dir)) { /* dir chg while moving? */ - if (uptr->STATE >= STA_ACC) { /* not stopping? */ - if (td_setpos (uptr)) return TRUE; /* update pos */ - sim_cancel (uptr); /* stop current */ - sim_activate (uptr, td_dctime); /* schedule decel */ - uptr->STATE = STA_DEC | prev_dir; /* set status */ - td_slf = td_qlf = td_qlctr = 0; } /* clear state */ - return FALSE; } +if ((prev_mving && !new_mving) || /* stop from moving? */ + (prev_dir != new_dir)) { /* dir chg while moving? */ + if (uptr->STATE >= STA_ACC) { /* not stopping? */ + if (td_setpos (uptr)) return TRUE; /* update pos */ + sim_cancel (uptr); /* stop current */ + sim_activate (uptr, td_dctime); /* schedule decel */ + uptr->STATE = STA_DEC | prev_dir; /* set status */ + td_slf = td_qlf = td_qlctr = 0; /* clear state */ + } + return FALSE; + } -return FALSE; +return FALSE; } - + /* 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/td_ltime) + t = time since operation started + tmax = time for operation (accel, decel only) + v = at speed velocity in lines (= 1/td_ltime) Then: - at speed dist = t * v - accel dist = (t^2 * v) / (2 * tmax) - decel dist = (((2 * t * tmax) - t^2) * v) / (2 * tmax) + 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. @@ -383,37 +401,44 @@ t_bool td_setpos (UNIT *uptr) uint32 new_time, ut, ulin, udelt; int32 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 (uptr->STATE & ~STA_DIR) { /* case on motion */ -case STA_STOP: /* stop */ - delta = 0; - break; -case STA_DEC: /* slowing */ - ulin = ut / (uint32) td_ltime; - udelt = td_dctime / td_ltime; - delta = ((ulin * udelt * 2) - (ulin * ulin)) / (2 * udelt); - break; -case STA_ACC: /* accelerating */ - ulin = ut / (uint32) td_ltime; - udelt = (td_dctime - (td_dctime >> 2)) / td_ltime; - delta = (ulin * ulin) / (2 * udelt); - break; -case STA_UTS: /* at speed */ - delta = ut / (uint32) td_ltime; - break; } -if (uptr->STATE & STA_DIR) uptr->pos = uptr->pos - delta; /* update pos */ +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 (uptr->STATE & ~STA_DIR) { /* case on motion */ + + case STA_STOP: /* stop */ + delta = 0; + break; + + case STA_DEC: /* slowing */ + ulin = ut / (uint32) td_ltime; + udelt = td_dctime / td_ltime; + delta = ((ulin * udelt * 2) - (ulin * ulin)) / (2 * udelt); + break; + + case STA_ACC: /* accelerating */ + ulin = ut / (uint32) td_ltime; + udelt = (td_dctime - (td_dctime >> 2)) / td_ltime; + delta = (ulin * ulin) / (2 * udelt); + break; + + case STA_UTS: /* at speed */ + delta = ut / (uint32) td_ltime; + break; + } + +if (uptr->STATE & STA_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 */ - sim_cancel (uptr); /* no timing pulses */ - return TRUE; } + detach_unit (uptr); /* off reel */ + sim_cancel (uptr); /* no timing pulses */ + return TRUE; + } return FALSE; } - + /* Unit service - unit is either changing speed, or it is up to speed */ t_stat td_svc (UNIT *uptr) @@ -430,36 +455,43 @@ int32 mtkb, datb; Accelerating - next state must be up to speed, fall through Up to speed - process line */ -if (mot == STA_STOP) return SCPE_OK; /* stopped? done */ -if ((uptr->flags & UNIT_ATT) == 0) { /* not attached? */ - uptr->STATE = uptr->pos = 0; /* also done */ - return SCPE_UNATT; } +if (mot == STA_STOP) return SCPE_OK; /* stopped? done */ +if ((uptr->flags & UNIT_ATT) == 0) { /* not attached? */ + uptr->STATE = uptr->pos = 0; /* also done */ + return SCPE_UNATT; + } -switch (mot) { /* case on motion */ -case STA_DEC: /* deceleration */ - if (td_setpos (uptr)) /* upd pos; off reel? */ - return IORETURN (td_stopoffr, STOP_DTOFF); - if ((unum != su) || !(td_cmd & TDC_STPGO)) /* not sel or stop? */ - uptr->STATE = 0; /* stop */ - else { /* selected and go */ - uptr->STATE = STA_ACC | /* accelerating */ - ((td_cmd & TDC_FWDRV)? STA_DIR: 0); /* in new dir */ - sim_activate (uptr, td_dctime - (td_dctime >> 2)); } - return SCPE_OK; -case STA_ACC: /* accelerating */ - if (td_setpos (uptr)) /* upd pos; off reel? */ - return IORETURN (td_stopoffr, STOP_DTOFF); - uptr->STATE = STA_UTS | dir; /* set up to speed */ - break; -case STA_UTS: /* up to speed */ - if (dir) uptr->pos = uptr->pos - 1; /* adjust position */ - else uptr->pos = uptr->pos + 1; - uptr->LASTT = sim_grtime (); /* save time */ - if (((int32) uptr->pos < 0) || /* off reel? */ - (uptr->pos >= (((uint32) DTU_FWDEZ (uptr)) + DT_EZLIN))) { - detach_unit (uptr); - return IORETURN (td_stopoffr, STOP_DTOFF); } - break; } /* check function */ +switch (mot) { /* case on motion */ + + case STA_DEC: /* deceleration */ + if (td_setpos (uptr)) /* upd pos; off reel? */ + return IORETURN (td_stopoffr, STOP_DTOFF); + if ((unum != su) || !(td_cmd & TDC_STPGO)) /* not sel or stop? */ + uptr->STATE = 0; /* stop */ + else { /* selected and go */ + uptr->STATE = STA_ACC | /* accelerating */ + ((td_cmd & TDC_FWDRV)? STA_DIR: 0); /* in new dir */ + sim_activate (uptr, td_dctime - (td_dctime >> 2)); + } + return SCPE_OK; + + case STA_ACC: /* accelerating */ + if (td_setpos (uptr)) /* upd pos; off reel? */ + return IORETURN (td_stopoffr, STOP_DTOFF); + uptr->STATE = STA_UTS | dir; /* set up to speed */ + break; + + case STA_UTS: /* up to speed */ + if (dir) uptr->pos = uptr->pos - 1; /* adjust position */ + else uptr->pos = uptr->pos + 1; + uptr->LASTT = sim_grtime (); /* save time */ + if (((int32) uptr->pos < 0) || /* off reel? */ + (uptr->pos >= (((uint32) DTU_FWDEZ (uptr)) + DT_EZLIN))) { + detach_unit (uptr); + return IORETURN (td_stopoffr, STOP_DTOFF); + } + break; /* check function */ + } /* At speed - process the current line @@ -471,58 +503,64 @@ case STA_UTS: /* up to speed */ the data register is shifted up. The complexity here comes from synthesizing the mark track, based on tape position, and the header data. */ -sim_activate (uptr, td_ltime); /* sched next line */ -if (unum != su) return SCPE_OK; /* not sel? done */ -td_slf = 1; /* set single */ -td_qlctr = (td_qlctr + 1) % DT_WSIZE; /* count words */ -if (td_qlctr == 0) { /* lines mod 4? */ - if (td_qlf) { /* quad line set? */ - td_tme = 1; /* timing error */ - td_cmd = td_cmd & ~TDC_RW; } /* clear write */ - else td_qlf = 1; } /* no, set quad */ +sim_activate (uptr, td_ltime); /* sched next line */ +if (unum != su) return SCPE_OK; /* not sel? done */ +td_slf = 1; /* set single */ +td_qlctr = (td_qlctr + 1) % DT_WSIZE; /* count words */ +if (td_qlctr == 0) { /* lines mod 4? */ + if (td_qlf) { /* quad line set? */ + td_tme = 1; /* timing error */ + td_cmd = td_cmd & ~TDC_RW; /* clear write */ + } + else td_qlf = 1; /* no, set quad */ + } -datb = 0; /* assume no data */ -if (uptr->pos < (DT_EZLIN - DT_BFLIN)) /* rev end zone? */ - mtkb = MTK_BIT (MTK_REV_END, uptr->pos); -else if (uptr->pos < DT_EZLIN) /* rev buffer? */ - mtkb = MTK_BIT (MTK_INTER, uptr->pos); -else if (uptr->pos < ((uint32) DTU_FWDEZ (uptr))) { /* data zone? */ - int32 blkno = DT_LIN2BL (uptr->pos, uptr); /* block # */ - int32 lineno = DT_LIN2OF (uptr->pos, uptr); /* line # within block */ - if (lineno < DT_HTLIN) { /* header? */ - if ((td_cmd & TDC_RW) == 0) /* read? */ - datb = td_header (uptr, blkno, lineno); } /* get nibble */ - else if (lineno < (DTU_LPERB (uptr) - DT_HTLIN)) { /* data? */ - if (td_cmd & TDC_RW) /* write? */ - td_write (uptr, blkno, /* write data nibble */ - lineno - DT_HTLIN, /* data rel line num */ - (td_dat >> 9) & 07); - else datb = td_read (uptr, blkno, /* no, read */ - lineno - DT_HTLIN); } - else if ((td_cmd & TDC_RW) == 0) /* trailer; read? */ - datb = td_trailer (uptr, blkno, lineno - /* get trlr nibble */ - (DTU_LPERB (uptr) - DT_HTLIN)); - mtkb = tdb_mtk[unum][lineno]; } +datb = 0; /* assume no data */ +if (uptr->pos < (DT_EZLIN - DT_BFLIN)) /* rev end zone? */ + mtkb = MTK_BIT (MTK_REV_END, uptr->pos); +else if (uptr->pos < DT_EZLIN) /* rev buffer? */ + mtkb = MTK_BIT (MTK_INTER, uptr->pos); +else if (uptr->pos < ((uint32) DTU_FWDEZ (uptr))) { /* data zone? */ + int32 blkno = DT_LIN2BL (uptr->pos, uptr); /* block # */ + int32 lineno = DT_LIN2OF (uptr->pos, uptr); /* line # within block */ + if (lineno < DT_HTLIN) { /* header? */ + if ((td_cmd & TDC_RW) == 0) /* read? */ + datb = td_header (uptr, blkno, lineno); /* get nibble */ + } + else if (lineno < (DTU_LPERB (uptr) - DT_HTLIN)) { /* data? */ + if (td_cmd & TDC_RW) /* write? */ + td_write (uptr, blkno, /* write data nibble */ + lineno - DT_HTLIN, /* data rel line num */ + (td_dat >> 9) & 07); + else datb = td_read (uptr, blkno, /* no, read */ + lineno - DT_HTLIN); + } + else if ((td_cmd & TDC_RW) == 0) /* trailer; read? */ + datb = td_trailer (uptr, blkno, lineno - /* get trlr nibble */ + (DTU_LPERB (uptr) - DT_HTLIN)); + mtkb = tdb_mtk[unum][lineno]; + } else if (uptr->pos < (((uint32) DTU_FWDEZ (uptr)) + DT_BFLIN)) - mtkb = MTK_BIT (MTK_INTER, uptr->pos); /* fwd buffer? */ -else mtkb = MTK_BIT (MTK_FWD_END, uptr->pos); /* fwd end zone */ + mtkb = MTK_BIT (MTK_INTER, uptr->pos); /* fwd buffer? */ +else mtkb = MTK_BIT (MTK_FWD_END, uptr->pos); /* fwd end zone */ -if (dir) { /* reverse? */ - mtkb = mtkb ^ 01; /* complement mark bit, */ - datb = datb ^ 07; } /* data bits */ -td_mtk = ((td_mtk << 1) | mtkb) & MTK_MASK; /* shift mark reg */ -td_dat = ((td_dat << 3) | datb) & 07777; /* shift data reg */ +if (dir) { /* reverse? */ + mtkb = mtkb ^ 01; /* complement mark bit, */ + datb = datb ^ 07; /* data bits */ + } +td_mtk = ((td_mtk << 1) | mtkb) & MTK_MASK; /* shift mark reg */ +td_dat = ((td_dat << 3) | datb) & 07777; /* shift data reg */ return SCPE_OK; } - + /* Header read - reads out 18b words in 3b increments - word lines contents - 0 0-5 0 - 1 6-11 block number - 2 12-17 0 - 3 18-23 0 - 4 24-29 reverse checksum (0777777) + word lines contents + 0 0-5 0 + 1 6-11 block number + 2 12-17 0 + 3 18-23 0 + 4 24-29 reverse checksum (0777777) */ int32 td_header (UNIT *uptr, int32 blk, int32 line) @@ -530,24 +568,28 @@ int32 td_header (UNIT *uptr, int32 blk, int32 line) int32 nibp; switch (line) { -case 8: case 9: case 10: case 11: /* block num */ - nibp = 3 * (DT_LPERMC - 1 - (line % DT_LPERMC)); - return (blk >> nibp) & 07; -case 24: case 25: case 26: case 27: case 28: case 29: /* rev csum */ - return 07; /* 777777 */ -default: - return 0; } + + case 8: case 9: case 10: case 11: /* block num */ + nibp = 3 * (DT_LPERMC - 1 - (line % DT_LPERMC)); + return (blk >> nibp) & 07; + + case 24: case 25: case 26: case 27: case 28: case 29: /* rev csum */ + return 07; /* 777777 */ + + default: + return 0; + } } /* Trailer read - reads out 18b words in 3b increments Checksum is stored to avoid double calculation - word lines contents - 0 0-5 forward checksum (lines 0-1, rest 0) - 1 6-11 0 - 2 12-17 0 - 3 18-23 reverse block mark - 4 24-29 0 + word lines contents + 0 0-5 forward checksum (lines 0-1, rest 0) + 1 6-11 0 + 2 12-17 0 + 3 18-23 reverse block mark + 4 24-29 0 Note that the reverse block mark (when read forward) appears as the complement obverse (3b nibbles swapped end for end and @@ -557,51 +599,56 @@ default: int32 td_trailer (UNIT *uptr, int32 blk, int32 line) { int32 nibp, i, ba; -int16 *fbuf= uptr->filebuf; +int16 *fbuf= (int16 *) uptr->filebuf; switch (line) { -case 0: - td_csum = 07777; /* init csum */ - ba = blk * DTU_BSIZE (uptr); - for (i = 0; i < DTU_BSIZE (uptr); i++) /* loop thru buf */ - td_csum = (td_csum ^ ~fbuf[ba + i]) & 07777; - td_csum = ((td_csum >> 6) ^ td_csum) & 077; + + case 0: + td_csum = 07777; /* init csum */ + ba = blk * DTU_BSIZE (uptr); + for (i = 0; i < DTU_BSIZE (uptr); i++) /* loop thru buf */ + td_csum = (td_csum ^ ~fbuf[ba + i]) & 07777; + td_csum = ((td_csum >> 6) ^ td_csum) & 077; return (td_csum >> 3) & 07; -case 1: - return (td_csum & 07); -case 18: case 19: case 20: case 21: - nibp = 3 * (line % DT_LPERMC); - return ((blk >> nibp) & 07) ^ 07; -default: - return 0; } + + case 1: + return (td_csum & 07); + + case 18: case 19: case 20: case 21: + nibp = 3 * (line % DT_LPERMC); + return ((blk >> nibp) & 07) ^ 07; + + default: + return 0; + } } /* Data read - convert block number/data line # to offset in data array */ int32 td_read (UNIT *uptr, int32 blk, int32 line) { -int16 *fbuf = uptr->filebuf; /* buffer */ -uint32 ba = blk * DTU_BSIZE (uptr); /* block base */ -int32 nibp = 3 * (DT_WSIZE - 1 - (line % DT_WSIZE)); /* nibble pos */ +int16 *fbuf = (int16 *) uptr->filebuf; /* buffer */ +uint32 ba = blk * DTU_BSIZE (uptr); /* block base */ +int32 nibp = 3 * (DT_WSIZE - 1 - (line % DT_WSIZE)); /* nibble pos */ -ba = ba + (line / DT_WSIZE); /* block addr */ -return (fbuf[ba] >> nibp) & 07; /* get data nibble */ +ba = ba + (line / DT_WSIZE); /* block addr */ +return (fbuf[ba] >> nibp) & 07; /* get data nibble */ } /* Data write - convert block number/data line # to offset in data array */ void td_write (UNIT *uptr, int32 blk, int32 line, int32 dat) { -int16 *fbuf = uptr->filebuf; /* buffer */ -uint32 ba = blk * DTU_BSIZE (uptr); /* block base */ -int32 nibp = 3 * (DT_WSIZE - 1 - (line % DT_WSIZE)); /* nibble pos */ +int16 *fbuf = (int16 *) uptr->filebuf; /* buffer */ +uint32 ba = blk * DTU_BSIZE (uptr); /* block base */ +int32 nibp = 3 * (DT_WSIZE - 1 - (line % DT_WSIZE)); /* nibble pos */ -ba = ba + (line / DT_WSIZE); /* block addr */ -fbuf[ba] = (fbuf[ba] & ~(07 << nibp)) | (dat << nibp); /* upd data nibble */ -if (ba >= uptr->hwmark) uptr->hwmark = ba + 1; /* upd length */ +ba = ba + (line / DT_WSIZE); /* block addr */ +fbuf[ba] = (fbuf[ba] & ~(07 << nibp)) | (dat << nibp); /* upd data nibble */ +if (ba >= uptr->hwmark) uptr->hwmark = ba + 1; /* upd length */ return; } - + /* Reset routine */ t_stat td_reset (DEVICE *dptr) @@ -609,20 +656,23 @@ t_stat td_reset (DEVICE *dptr) int32 i; UNIT *uptr; -for (i = 0; i < DT_NUMDR; i++) { /* stop all activity */ - uptr = td_dev.units + i; - if (sim_is_running) { /* CAF? */ - if (uptr->STATE >= STA_ACC) { /* accel or uts? */ - if (td_setpos (uptr)) continue; /* update pos */ - sim_cancel (uptr); - sim_activate (uptr, td_dctime); /* sched decel */ - uptr->STATE = STA_DEC | (uptr->STATE & STA_DIR); - } } - else { - sim_cancel (uptr); /* sim reset */ - uptr->STATE = 0; - uptr->LASTT = sim_grtime (); } } -td_slf = td_qlf = td_qlctr = 0; /* clear state */ +for (i = 0; i < DT_NUMDR; i++) { /* stop all activity */ + uptr = td_dev.units + i; + if (sim_is_running) { /* CAF? */ + if (uptr->STATE >= STA_ACC) { /* accel or uts? */ + if (td_setpos (uptr)) continue; /* update pos */ + sim_cancel (uptr); + sim_activate (uptr, td_dctime); /* sched decel */ + uptr->STATE = STA_DEC | (uptr->STATE & STA_DIR); + } + } + else { + sim_cancel (uptr); /* sim reset */ + uptr->STATE = 0; + uptr->LASTT = sim_grtime (); + } + } +td_slf = td_qlf = td_qlctr = 0; /* clear state */ td_cmd = td_dat = td_mtk = 0; td_csum = 0; return SCPE_OK; @@ -640,52 +690,52 @@ return SCPE_OK; 4) Continue at location 7400. */ -#define BOOT_START 07300 -#define BOOT_LEN (sizeof (boot_rom) / sizeof (int16)) +#define BOOT_START 07300 +#define BOOT_LEN (sizeof (boot_rom) / sizeof (int16)) static const uint16 boot_rom[] = { - 01312, /* ST, TAD L4MT ;=2000, reverse */ - 04312, /* JMS L4MT ; rev lk for 022 */ - 04312, /* JMS L4MT ; fwd lk for 031 */ - 06773, /* DAT, SDSQ ; wait for 12b */ - 05303, /* JMP .-1 */ - 06777, /* SDRD ; read word */ - 03726, /* DCA I BUF ; store */ - 02326, /* ISZ BUF ; incr ptr */ - 05303, /* JMP DAT ; if not 0, cont */ - 05732, /* JMP I SCB ; jump to boot */ - 02000, /* L4MT,2000 ; overwritten */ - 01300, /* TAD ST ; =1312, go */ - 06774, /* SDLC ; new command */ - 06771, /* MTK, SDSS ; wait for mark */ - 05315, /* JMP .-1 */ - 06776, /* SDRC ; get mark code */ - 00331, /* AND K77 ; mask to 6b */ - 01327, /* CMP, TAD MCD ; got target code? */ - 07640, /* SZA CLA ; skip if yes */ - 05315, /* JMP MTK ; wait for mark */ - 02321, /* ISZ CMP ; next target */ - 05712, /* JMP I L4MT ; exit */ - 07354, /* BUF, 7354 ; loading point */ - 07756, /* MCD, -22 ; target 1 */ - 07747, /* -31 ; target 2 */ - 00077, /* 77 ; mask */ - 07400 /* SCB, 7400 ; secondary boot */ -}; + 01312, /* ST, TAD L4MT ;=2000, reverse */ + 04312, /* JMS L4MT ; rev lk for 022 */ + 04312, /* JMS L4MT ; fwd lk for 031 */ + 06773, /* DAT, SDSQ ; wait for 12b */ + 05303, /* JMP .-1 */ + 06777, /* SDRD ; read word */ + 03726, /* DCA I BUF ; store */ + 02326, /* ISZ BUF ; incr ptr */ + 05303, /* JMP DAT ; if not 0, cont */ + 05732, /* JMP I SCB ; jump to boot */ + 02000, /* L4MT,2000 ; overwritten */ + 01300, /* TAD ST ; =1312, go */ + 06774, /* SDLC ; new command */ + 06771, /* MTK, SDSS ; wait for mark */ + 05315, /* JMP .-1 */ + 06776, /* SDRC ; get mark code */ + 00331, /* AND K77 ; mask to 6b */ + 01327, /* CMP, TAD MCD ; got target code? */ + 07640, /* SZA CLA ; skip if yes */ + 05315, /* JMP MTK ; wait for mark */ + 02321, /* ISZ CMP ; next target */ + 05712, /* JMP I L4MT ; exit */ + 07354, /* BUF, 7354 ; loading point */ + 07756, /* MCD, -22 ; target 1 */ + 07747, /* -31 ; target 2 */ + 00077, /* 77 ; mask */ + 07400 /* SCB, 7400 ; secondary boot */ + }; t_stat td_boot (int32 unitno, DEVICE *dptr) { int32 i; extern int32 saved_PC; -if (unitno) return SCPE_ARG; /* only unit 0 */ -if (td_dib.dev != DEV_TD8E) return STOP_NOTSTD; /* only std devno */ +if (unitno) return SCPE_ARG; /* only unit 0 */ +if (td_dib.dev != DEV_TD8E) return STOP_NOTSTD; /* only std devno */ td_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 @@ -704,58 +754,64 @@ int32 u = uptr - td_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 (uptr->fileref))) { - 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 */ +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 (uptr->fileref))) { + 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; } -fbuf = uptr->filebuf; /* file buffer */ +if (uptr->filebuf == NULL) { /* can't alloc? */ + detach_unit (uptr); + return SCPE_MEM; + } +fbuf = (uint16 *) uptr->filebuf; /* file buffer */ printf ("%s%d: ", sim_dname (&td_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 */ - fbuf[ba] = (pdp18b[k] >> 6) & 07777; - fbuf[ba + 1] = ((pdp18b[k] & 077) << 6) | - ((pdp18b[k + 1] >> 12) & 077); - fbuf[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 */ -uptr->STATE = STA_STOP; /* stopped */ +if (uptr->flags & UNIT_8FMT) /* 12b? */ + uptr->hwmark = fxread (uptr->filebuf, sizeof (uint16), + 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 (uint16), D18_NBSIZE, uptr->fileref); + for (i = 0; i < k; i++) pdp18b[i] = pdp11b[i]; + } + else k = fxread (pdp18b, sizeof (uint32), 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 */ + fbuf[ba] = (pdp18b[k] >> 6) & 07777; + fbuf[ba + 1] = ((pdp18b[k] & 077) << 6) | + ((pdp18b[k + 1] >> 12) & 077); + fbuf[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 */ +uptr->STATE = STA_STOP; /* stopped */ -mtkpb = (DTU_BSIZE (uptr) * DT_WSIZE) / DT_LPERMC; /* mtk codes per blk */ -k = td_set_mtk (MTK_INTER, u, 0); /* fill mark track */ -k = td_set_mtk (MTK_FWD_BLK, u, k); /* bit array */ +mtkpb = (DTU_BSIZE (uptr) * DT_WSIZE) / DT_LPERMC; /* mtk codes per blk */ +k = td_set_mtk (MTK_INTER, u, 0); /* fill mark track */ +k = td_set_mtk (MTK_FWD_BLK, u, k); /* bit array */ k = td_set_mtk (MTK_REV_GRD, u, k); for (i = 0; i < 4; i++) k = td_set_mtk (MTK_FWD_PRE, u, k); for (i = 0; i < (mtkpb - 4); i++) k = td_set_mtk (MTK_DATA, u, k); @@ -782,38 +838,40 @@ int32 u = uptr - td_dev.units; uint32 ba; if (!(uptr->flags & UNIT_ATT)) return SCPE_OK; -fbuf = uptr->filebuf; /* file buffer */ -if (uptr->hwmark && ((uptr->flags & UNIT_RO)== 0)) { /* any data? */ - printf ("%s%d: writing buffer to file\n", sim_dname (&td_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) (fbuf[ba] & 07777) << 6) | - ((uint32) (fbuf[ba + 1] >> 6) & 077); - pdp18b[k + 1] = ((uint32) (fbuf[ba + 1] & 077) << 12) | - ((uint32) (fbuf[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 */ +fbuf = (uint16 *) uptr->filebuf; /* file buffer */ +if (uptr->hwmark && ((uptr->flags & UNIT_RO)== 0)) { /* any data? */ + printf ("%s%d: writing buffer to file\n", sim_dname (&td_dev), u); + rewind (uptr->fileref); /* start of file */ + if (uptr->flags & UNIT_8FMT) /* PDP8? */ + fxwrite (uptr->filebuf, sizeof (uint16), /* 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) (fbuf[ba] & 07777) << 6) | + ((uint32) (fbuf[ba + 1] >> 6) & 077); + pdp18b[k + 1] = ((uint32) (fbuf[ba + 1] & 077) << 12) | + ((uint32) (fbuf[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 (uint16), + D18_NBSIZE, uptr->fileref); + } + else fxwrite (pdp18b, sizeof (uint32), + 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 */ uptr->pos = uptr->STATE = 0; -sim_cancel (uptr); /* no more pulses */ +sim_cancel (uptr); /* no more pulses */ return detach_unit (uptr); } @@ -832,22 +890,23 @@ return k; t_stat td_show_pos (FILE *st, UNIT *uptr, int32 val, void *desc) { if ((uptr->flags & UNIT_ATT) == 0) return SCPE_UNATT; -if (uptr->pos < DT_EZLIN) /* rev end zone? */ - fprintf (st, "Reverse end zone\n"); -else if (uptr->pos < ((uint32) DTU_FWDEZ (uptr))) { /* data zone? */ - int32 blkno = DT_LIN2BL (uptr->pos, uptr); /* block # */ - int32 lineno = DT_LIN2OF (uptr->pos, uptr); /* line # within block */ - fprintf (st, "Block %d, line %d, ", blkno, lineno); - if (lineno < DT_HTLIN) /* header? */ - fprintf (st, "header cell %d, nibble %d\n", - lineno / DT_LPERMC, lineno % DT_LPERMC); - else if (lineno < (DTU_LPERB (uptr) - DT_HTLIN)) /* data? */ - fprintf (st, "data word %d, nibble %d\n", - (lineno - DT_HTLIN) / DT_WSIZE, (lineno - DT_HTLIN) % DT_WSIZE); - else fprintf (st, "trailer cell %d, nibble %d\n", - (lineno - (DTU_LPERB (uptr) - DT_HTLIN)) / DT_LPERMC, - (lineno - (DTU_LPERB (uptr) - DT_HTLIN)) % DT_LPERMC); } -else fprintf (st, "Forward end zone\n"); /* fwd end zone */ +if (uptr->pos < DT_EZLIN) /* rev end zone? */ + fprintf (st, "Reverse end zone\n"); +else if (uptr->pos < ((uint32) DTU_FWDEZ (uptr))) { /* data zone? */ + int32 blkno = DT_LIN2BL (uptr->pos, uptr); /* block # */ + int32 lineno = DT_LIN2OF (uptr->pos, uptr); /* line # within block */ + fprintf (st, "Block %d, line %d, ", blkno, lineno); + if (lineno < DT_HTLIN) /* header? */ + fprintf (st, "header cell %d, nibble %d\n", + lineno / DT_LPERMC, lineno % DT_LPERMC); + else if (lineno < (DTU_LPERB (uptr) - DT_HTLIN)) /* data? */ + fprintf (st, "data word %d, nibble %d\n", + (lineno - DT_HTLIN) / DT_WSIZE, (lineno - DT_HTLIN) % DT_WSIZE); + else fprintf (st, "trailer cell %d, nibble %d\n", + (lineno - (DTU_LPERB (uptr) - DT_HTLIN)) / DT_LPERMC, + (lineno - (DTU_LPERB (uptr) - DT_HTLIN)) % DT_LPERMC); + } +else fprintf (st, "Forward end zone\n"); /* fwd end zone */ return SCPE_OK; } diff --git a/PDP8/pdp8_tsc.c b/PDP8/pdp8_tsc.c index 21f90590..15be1845 100644 --- a/PDP8/pdp8_tsc.c +++ b/PDP8/pdp8_tsc.c @@ -1,6 +1,6 @@ /* pdp8_tsc.c: PDP-8 ETOS timesharing option board (TSC8-75) - Copyright (c) 2003-2004, Robert M Supnik + Copyright (c) 2003-2005, 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"), @@ -19,46 +19,46 @@ 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 + 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 is based on Bernhard Baehr's PDP-8/E simulator - PDP-8/E Simulator Source Code + PDP-8/E Simulator Source Code - Copyright ) 2001-2003 Bernhard Baehr + Copyright ) 2001-2003 Bernhard Baehr - TSC8iots.c - IOTs for the TSC8-75 Board plugin + TSC8iots.c - IOTs for the TSC8-75 Board plugin - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - tsc TSC8-75 option board + tsc TSC8-75 option board */ #include "pdp8_defs.h" extern int32 int_req; extern int32 SF; -extern int32 tsc_ir; /* "ERIOT" */ -extern int32 tsc_pc; /* "ERTB" */ -extern int32 tsc_cdf; /* "ECDF" */ -extern int32 tsc_enb; /* enable */ +extern int32 tsc_ir; /* "ERIOT" */ +extern int32 tsc_pc; /* "ERTB" */ +extern int32 tsc_cdf; /* "ECDF" */ +extern int32 tsc_enb; /* enable */ -#define UNIT_V_SN699 (UNIT_V_UF + 0) /* SN 699 or above */ -#define UNIT_SN699 (1 << UNIT_V_SN699) +#define UNIT_V_SN699 (UNIT_V_UF + 0) /* SN 699 or above */ +#define UNIT_SN699 (1 << UNIT_V_SN699) DEVICE tsc_dev; int32 tsc (int32 IR, int32 AC); @@ -66,9 +66,9 @@ t_stat tsc_reset (DEVICE *dptr); /* TSC data structures - tsc_dev TSC device descriptor - tsc_unit TSC unit descriptor - tsc_reg TSC register list + tsc_dev TSC device descriptor + tsc_unit TSC unit descriptor + tsc_reg TSC register list */ DIB tsc_dib = { DEV_TSC, 1, { &tsc } }; @@ -76,57 +76,72 @@ DIB tsc_dib = { DEV_TSC, 1, { &tsc } }; UNIT tsc_unit = { UDATA (NULL, UNIT_SN699, 0) }; REG tsc_reg[] = { - { ORDATA (IR, tsc_ir, 12) }, - { ORDATA (PC, tsc_pc, 12) }, - { FLDATA (CDF, tsc_cdf, 0) }, - { FLDATA (ENB, tsc_enb, 0) }, - { FLDATA (INT, int_req, INT_V_TSC) }, - { NULL } }; + { ORDATA (IR, tsc_ir, 12) }, + { ORDATA (PC, tsc_pc, 12) }, + { FLDATA (CDF, tsc_cdf, 0) }, + { FLDATA (ENB, tsc_enb, 0) }, + { FLDATA (INT, int_req, INT_V_TSC) }, + { NULL } + }; MTAB tsc_mod[] = { - { UNIT_SN699, UNIT_SN699, "ESME", "ESME", NULL }, - { UNIT_SN699, 0, "no ESME", "NOESME", NULL }, - { 0 } }; + { UNIT_SN699, UNIT_SN699, "ESME", "ESME", NULL }, + { UNIT_SN699, 0, "no ESME", "NOESME", NULL }, + { 0 } + }; DEVICE tsc_dev = { - "TSC", &tsc_unit, tsc_reg, tsc_mod, - 1, 10, 31, 1, 8, 8, - NULL, NULL, &tsc_reset, - NULL, NULL, NULL, - &tsc_dib, DEV_DISABLE | DEV_DIS }; - + "TSC", &tsc_unit, tsc_reg, tsc_mod, + 1, 10, 31, 1, 8, 8, + NULL, NULL, &tsc_reset, + NULL, NULL, NULL, + &tsc_dib, DEV_DISABLE | DEV_DIS + }; + /* IOT routine */ int32 tsc (int32 IR, int32 AC) { -switch (IR & 07) { /* decode IR<9:11> */ -case 0: /* ETDS */ - tsc_enb = 0; /* disable int req */ - int_req = int_req & ~INT_TSC; /* clear flag */ - break; -case 1: /* ESKP */ - return (int_req & INT_TSC)? IOT_SKP + AC: AC; /* skip on int req */ -case 2: /* ECTF */ - int_req = int_req & ~INT_TSC; /* clear int req */ - break; -case 3: /* ECDF */ - AC = AC | ((tsc_ir >> 3) & 07); /* read "ERIOT"<6:8> */ - if (tsc_cdf) AC = AC | IOT_SKP; /* if cdf, skip */ - tsc_cdf = 0; - break; -case 4: /* ERTB */ - return tsc_pc; -case 5: /* ESME */ - if (tsc_unit.flags & UNIT_SN699) { /* enabled? */ - if (tsc_cdf && ((tsc_ir & 070) >> 3) == (SF & 07)) { - AC = AC | IOT_SKP; - tsc_cdf = 0; } } - break; -case 6: /* ERIOT */ - return tsc_ir; -case 7: /* ETEN */ - tsc_enb = 1; - break; } /* end switch */ +switch (IR & 07) { /* decode IR<9:11> */ + + case 0: /* ETDS */ + tsc_enb = 0; /* disable int req */ + int_req = int_req & ~INT_TSC; /* clear flag */ + break; + + case 1: /* ESKP */ + return (int_req & INT_TSC)? IOT_SKP + AC: AC; /* skip on int req */ + + case 2: /* ECTF */ + int_req = int_req & ~INT_TSC; /* clear int req */ + break; + + case 3: /* ECDF */ + AC = AC | ((tsc_ir >> 3) & 07); /* read "ERIOT"<6:8> */ + if (tsc_cdf) AC = AC | IOT_SKP; /* if cdf, skip */ + tsc_cdf = 0; + break; + + case 4: /* ERTB */ + return tsc_pc; + + case 5: /* ESME */ + if (tsc_unit.flags & UNIT_SN699) { /* enabled? */ + if (tsc_cdf && ((tsc_ir & 070) >> 3) == (SF & 07)) { + AC = AC | IOT_SKP; + tsc_cdf = 0; + } + } + break; + + case 6: /* ERIOT */ + return tsc_ir; + + case 7: /* ETEN */ + tsc_enb = 1; + break; + } /* end switch */ + return AC; } diff --git a/PDP8/pdp8_tt.c b/PDP8/pdp8_tt.c index 295c1466..1c6ab891 100644 --- a/PDP8/pdp8_tt.c +++ b/PDP8/pdp8_tt.c @@ -1,6 +1,6 @@ /* pdp8_tt.c: PDP-8 console terminal simulator - Copyright (c) 1993-2004, Robert M Supnik + Copyright (c) 1993-2005, 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"), @@ -19,30 +19,30 @@ 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 + 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 + tti,tto KL8E terminal input/output - 28-May-04 RMS Removed SET TTI CTRL-C - 29-Dec-03 RMS Added console output backpressure support - 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 + 28-May-04 RMS Removed SET TTI CTRL-C + 29-Dec-03 RMS Added console output backpressure support + 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) +#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; @@ -53,13 +53,13 @@ t_stat tto_svc (UNIT *uptr); t_stat tti_reset (DEVICE *dptr); t_stat tto_reset (DEVICE *dptr); 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 + 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 } }; @@ -67,34 +67,37 @@ 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 } }; + { 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, 0, "DEVNO", NULL, NULL, &show_dev, NULL }, - { 0 } }; + { 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, 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 }; + "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 + tto_dev TTO device descriptor + tto_unit TTO unit descriptor + tto_reg TTO register list */ DIB tto_dib = { DEV_TTO, 1, { &tto } }; @@ -102,56 +105,66 @@ 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 } }; + { 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 } }; + { 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 }; - + "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 */ +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 */ @@ -160,17 +173,18 @@ 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 */ +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 */ +dev_done = dev_done | INT_TTI; /* set done */ +int_req = INT_UPDATE; /* update interrupts */ return SCPE_OK; } @@ -179,39 +193,46 @@ return SCPE_OK; t_stat tti_reset (DEVICE *dptr) { tti_unit.buf = 0; -dev_done = dev_done & ~INT_TTI; /* clear done, int */ +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 */ +int_enable = int_enable | INT_TTI; /* set enable */ +sim_activate (&tti_unit, tti_unit.wait); /* activate unit */ 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 */ +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 */ @@ -221,15 +242,17 @@ t_stat tto_svc (UNIT *uptr) int32 c; t_stat r; -if (tto_unit.flags & UNIT_KSR) { /* UC only? */ - c = tto_unit.buf & 0177; - if (islower (c)) c = toupper (c); } +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_s (c)) != SCPE_OK) { /* output char; error? */ - sim_activate (uptr, uptr->wait); /* try again */ - return ((r == SCPE_STALL)? SCPE_OK: r); } /* if !stall, report */ -dev_done = dev_done | INT_TTO; /* set done */ -int_req = INT_UPDATE; /* update interrupts */ +if ((r = sim_putchar_s (c)) != SCPE_OK) { /* output char; error? */ + sim_activate (uptr, uptr->wait); /* try again */ + return ((r == SCPE_STALL)? SCPE_OK: r); /* if !stall, report */ + } +dev_done = dev_done | INT_TTO; /* set done */ +int_req = INT_UPDATE; /* update interrupts */ tto_unit.pos = tto_unit.pos + 1; return SCPE_OK; } @@ -239,10 +262,10 @@ return SCPE_OK; t_stat tto_reset (DEVICE *dptr) { tto_unit.buf = 0; -dev_done = dev_done & ~INT_TTO; /* clear done, int */ +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 */ +int_enable = int_enable | INT_TTO; /* set enable */ +sim_cancel (&tto_unit); /* deactivate unit */ return SCPE_OK; } diff --git a/PDP8/pdp8_ttx.c b/PDP8/pdp8_ttx.c index fd2cd250..e5e1a944 100644 --- a/PDP8/pdp8_ttx.c +++ b/PDP8/pdp8_ttx.c @@ -1,6 +1,6 @@ /* pdp8_ttx.c: PDP-8 additional terminals simulator - Copyright (c) 1993-2004, Robert M Supnik + Copyright (c) 1993-2005, 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"), @@ -19,22 +19,25 @@ 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 + 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 + ttix,ttox PT08/KL8JA terminal input/output - 05-Jan-04 RMS Revised for tmxr library changes - 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 + 29-Jun-05 RMS Added SET TTOXn DISCONNECT + Fixed bug in SET LOG/NOLOG + 21-Jun-05 RMS Fixed bug in SHOW CONN/STATS + 05-Jan-04 RMS Revised for tmxr library changes + 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 @@ -47,23 +50,23 @@ #include "sim_tmxr.h" #include -#define TTX_LINES 4 -#define TTX_MASK (TTX_LINES - 1) +#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 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) +#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 = { TTX_LINES, 0, 0, ttx_ldsc }; /* mux descriptor */ +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 = { TTX_LINES, 0, 0, ttx_ldsc }; /* mux descriptor */ DEVICE ttix_dev, ttox_dev; int32 ttix (int32 IR, int32 AC); @@ -77,121 +80,139 @@ 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 + 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 } }; + { &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 } }; + { 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 }, - { MTAB_XTD|MTAB_VUN|MTAB_NC, 0, "LOG", "LOG", - &tmxr_set_log, &tmxr_show_log, &ttx_desc }, - { MTAB_XTD|MTAB_VUN|MTAB_NC, 0, NULL, "NOLOG", - &tmxr_set_nolog, NULL, &ttx_desc }, - { 0 } }; + { 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 }; + "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 + 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 } }; + { 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 } }; + { 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 } }; + { 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 }, + { MTAB_XTD|MTAB_VUN, 0, NULL, "DISCONNECT", + &tmxr_dscln, NULL, &ttx_desc }, + { MTAB_XTD|MTAB_VUN|MTAB_NC, 0, "LOG", "LOG", + &tmxr_set_log, &tmxr_show_log, &ttx_desc }, + { MTAB_XTD|MTAB_VUN|MTAB_NC, 0, NULL, "NOLOG", + &tmxr_set_nolog, NULL, &ttx_desc }, + { 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 }; - + "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 */ +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 */ -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; } @@ -201,24 +222,27 @@ 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; } } } +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) ttx_ldsc[ln].rcve = 1; /* got one? rcv enb*/ +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; } @@ -228,52 +252,63 @@ 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 */ +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 */ +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 */ -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; } @@ -281,23 +316,27 @@ return AC; t_stat ttox_svc (UNIT *uptr) { -int32 c, ln = uptr - ttox_unit; /* line # */ +int32 c, ln = uptr - ttox_unit; /* line # */ -if (ttx_ldsc[ln].conn) { /* connected? */ - if (ttx_ldsc[ln].xmte) { /* tx enabled? */ - TMLN *lp = &ttx_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 */ +if (ttx_ldsc[ln].conn) { /* connected? */ + if (ttx_ldsc[ln].xmte) { /* tx enabled? */ + TMLN *lp = &ttx_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; } @@ -307,17 +346,18 @@ 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 */ +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) @@ -325,10 +365,10 @@ 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 */ +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; } @@ -339,10 +379,11 @@ 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_ldsc[i].rcve = 0; /* disable rcv */ - sim_cancel (&ttox_unit[i]); } /* stop poll */ +r = tmxr_detach (&ttx_desc, uptr); /* detach */ +for (i = 0; i < TTX_LINES; i++) { /* all lines, */ + ttx_ldsc[i].rcve = 0; /* disable rcv */ + sim_cancel (&ttox_unit[i]); /* stop poll */ + } return r; } @@ -362,14 +403,17 @@ return SCPE_OK; t_stat ttx_show (FILE *st, UNIT *uptr, int32 val, void *desc) { -int32 i; +int32 i, t; -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); } } +for (i = t = 0; i < TTX_LINES; i++) t = t + (ttx_ldsc[i].conn != 0); +if (t) { + 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; } @@ -379,9 +423,12 @@ return SCPE_OK; 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; } + 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/S3/s3_cd.c b/S3/s3_cd.c index 77423b19..5221c775 100644 --- a/S3/s3_cd.c +++ b/S3/s3_cd.c @@ -1,6 +1,6 @@ /* s3_cd.c: IBM 1442 card reader/punch - Copyright (c) 2001-2003, Charles E. Owen + Copyright (c) 2001-2005, 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"), @@ -19,16 +19,16 @@ 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 + 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 + 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 + 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 @@ -43,7 +43,7 @@ extern uint8 M[]; extern char ebcdic_to_ascii[256]; extern char ascii_to_ebcdic[256]; int32 s1sel, s2sel; -char rbuf[CBUFSIZE]; /* > CDR_WIDTH */ +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); @@ -51,92 +51,97 @@ 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 */ +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 + 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 }; +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 } }; + { 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 }; + "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 + 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) }; +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 } }; + { 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 }; + "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 + 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) } +}; REG stack_reg[] = { - { DRDATA (POS0, stack_unit[0].pos, 32), PV_LEFT }, - { NULL } }; + { 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 }; + "CDP2", stack_unit, stack_reg, NULL, + 1, 10, 31, 1, 8, 7, + NULL, NULL, &cd_reset, + NULL, NULL, NULL +}; /* -------------------------------------------------------------------- */ @@ -145,126 +150,126 @@ DEVICE stack_dev = { 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; + 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 + mod 0 = ASCII read + mod 1 = EBCDIC read */ t_stat read_card (int32 ilnt, int32 mod) @@ -272,59 +277,59 @@ 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 (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; + (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 */ +lastcard = carderr = notready = s1sel = s2sel = 0; /* default stacker */ -for (i = 0; i < CBUFSIZE; i++) rbuf[i] = 0x20; /* clear buffer */ +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 */ + 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++; +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 */ +sim_activate (&cdr_unit, cdr_unit.wait); /* activate */ return SCPE_OK; } @@ -337,22 +342,22 @@ 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? */ +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); +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 */ +uptr -> pos = ftell (uptr -> fileref); /* update position */ return SCPE_OK; } - + /* Card punch routine mod: not used @@ -361,44 +366,44 @@ return SCPE_OK; t_stat punch_card (int32 ilnt, int32 mod) { int32 i, colcount; -static char pbuf[CDP_WIDTH + 1]; /* + null */ +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; +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 */ +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 = 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 */ +pbuf[CDP_WIDTH] = 0; /* trailing null */ if (!cdp_ebcdic) { - fputs (pbuf, uptr -> fileref); /* output card */ - fputc ('\n', uptr -> fileref); /* plus new line */ + 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; + 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 */ +uptr -> pos = ftell (uptr -> fileref); /* update position */ return SCPE_OK; } - + /* Select stack routine Modifiers have been checked by the caller @@ -416,9 +421,9 @@ return SCPE_OK; 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 */ +lastcard = carderr = notready = pcherror = 0; /* clear indicators */ +s1sel = s2sel = 0; /* clear stacker sel */ +sim_cancel (&cdr_unit); /* clear reader event */ return SCPE_OK; } @@ -426,7 +431,7 @@ return SCPE_OK; t_stat cdr_attach (UNIT *uptr, char *cptr) { -carderr = lastcard = notready = 0; /* clear last card */ +carderr = lastcard = notready = 0; /* clear last card */ return attach_unit (uptr, cptr); } diff --git a/S3/s3_cpu.c b/S3/s3_cpu.c index ca6abd63..4655773f 100644 --- a/S3/s3_cpu.c +++ b/S3/s3_cpu.c @@ -1,6 +1,6 @@ /* s3_cpu.c: IBM System/3 CPU simulator - Copyright (c) 2001-2003, Charles E. Owen + Copyright (c) 2001-2005, Charles E. Owen HPL & SLC instruction code Copyright (c) 2001 by Henk Stegeman Decimal Arithmetic Copyright (c) 2000 by Roger Bowler @@ -21,13 +21,13 @@ 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 + 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 + 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 @@ -69,14 +69,14 @@ 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) + 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 @@ -92,12 +92,12 @@ { --- } <---------------- 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 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 + 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, @@ -109,52 +109,52 @@ | Opcode | | Q-byte | | R-byte + +------------+ +------------+ +------------+ - (The meaning of Q-byte and R-byte defined by the operation) - - + (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: + Direct Addressing Format: +------------+ +------------+ +-----------+----------+ | Opcode | | Q-byte | | MSB + LSB + +------------+ +------------+ +-----------+----------+ - Base-Displacement Format: + 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 - + + 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): + Operand 1 Address Direct (opcodes 0001 or 0010): +------------+ +------------+ +----------+----------+ +------------+ | Opcode | | Q-byte | | MSB + LSB + |displacement| +------------+ +------------+ +----------+----------+ +------------+ - Operand 2 Address Direct (opcodes 0100 or 1000): + Operand 2 Address Direct (opcodes 0100 or 1000): +------------+ +------------+ +------------+ +----------+----------+ | Opcode | | Q-byte | |displacement| | MSB + LSB + +------------+ +------------+ +------------+ +----------+----------+ - Both Addresses Direct (opcode 0000): + Both Addresses Direct (opcode 0000): +------------+ +------------+ +----------+----------+ +-----------+----------+ | Opcode | | Q-byte | | MSB + LSB + + MSB + LSB + +------------+ +------------+ +----------+----------+ +-----------+----------+ - Both Addresses Displacement (opcodes 0101, 0110, 1001, or 1010): + Both Addresses Displacement (opcodes 0101, 0110, 1001, or 1010): +------------+ +------------+ +------------+ +------------+ | Opcode | | Q-byte | |displacement| |displacement| @@ -175,23 +175,23 @@ 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) - + 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. @@ -199,90 +199,90 @@ in the range 1-256. No-address formats: ------------------ - HPL hex,hex Halt Program Level, the operands are the Q and R bytes + 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 + 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 + 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) + 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 + 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 + 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. - + 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 + 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 @@ -312,9 +312,8 @@ Dx | BC TIO LA - - - - - - - - - - - - - Ex | BC TIO LA - - - - - - - - - - - - - Fx | HPL APL JC SIO - - - - - - - - - - - - -*/ - -/* This routine is the instruction decode routine for System/3. + + 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. @@ -323,11 +322,11 @@ Fx | HPL APL JC SIO - - - - - - - - - - - - 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 + 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. @@ -350,39 +349,39 @@ Fx | HPL APL JC SIO - - - - - - - - - - - - 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 + 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_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_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) +#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 */ +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 */ +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); @@ -397,7 +396,7 @@ 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, uint32 *val, - UNIT *uptr, int32 sw); + 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); @@ -409,99 +408,101 @@ 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 */ + { 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 + 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 } }; + { 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 } }; + { 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 }; - + "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; @@ -517,397 +518,398 @@ register t_stat reason; /* Restore register state */ -PC = IAR[level]; /* load local PC */ +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; } +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 (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; +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; -} + fclose(trace); + debug_flag = 0; +} if (debug_reg) { - if (!debug_flag) { - trace = fopen("trace.log", "w"); - debug_flag = 1; - } + 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"); + 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 */ +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 */ +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; +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) */ + 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) */ + 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; + 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; @@ -915,380 +917,380 @@ switch (opaddr) { carry = 1; else carry = 0; - if ((IR & 0xFF) != 0) zero = 0; /* HJS mod */ + if ((IR & 0xFF) != 0) zero = 0; /* HJS mod */ PutMem(BAR,(IR & 0xFF)); BAR--; AAR--; qbyte--; } - PSR &= 0xF8; - if (zero) - PSR |= 0x01; /* Equal */ + PSR &= 0xF8; + if (zero) + PSR |= 0x01; /* Equal */ if (!zero && !carry) - PSR |= 0x02; /* Low */ + 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) */ - + 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; @@ -1319,28 +1321,28 @@ int32 PutMem(int32 addr, int32 data) 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); + 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 @@ -1351,14 +1353,14 @@ int32 compare(int32 byte1, int32 byte2, int32 cond) { int32 r; - r = cond & 0xF8; /* mask off all but unaffected bits 2,3,4 */ + r = cond & 0xF8; /* mask off all but unaffected bits 2,3,4 */ if (byte1 == byte2) - r |= 0x01; /* set equal bit */ + r |= 0x01; /* set equal bit */ if (byte1 < byte2) - r |= 0x02; /* set less-than bit */ + r |= 0x02; /* set less-than bit */ if (byte1 > byte2) - r |= 0x04; /* set greater than bit */ - return r; + r |= 0x04; /* set greater than bit */ + return r; } /*-------------------------------------------------------------------*/ @@ -1396,7 +1398,7 @@ int sign1, sign2, sign3; /* Sign of operands & result */ /* Add or subtract operand values */ if (count2 == 0) { - /* If second operand is zero then result is first operand */ + /* If second operand is zero then result is first operand */ memcpy (dec3, dec1, MAX_DECIMAL_DIGITS); count3 = count1; sign3 = sign1; @@ -1438,7 +1440,7 @@ int sign1, sign2, sign3; /* Sign of operands & result */ /* Return condition code */ return cc; -} /* end function add_packed */ +} /* end function add_packed */ /*-------------------------------------------------------------------*/ /* Subtract two zoned decimal operands */ @@ -1517,7 +1519,7 @@ int sign1, sign2, sign3; /* Sign of operands & result */ /* Return condition code */ return cc; -} /* end function subtract_packed */ +} /* end function subtract_packed */ /*-------------------------------------------------------------------*/ @@ -1552,7 +1554,7 @@ int carry = 0; /* Carry indicator */ /* Add digits from first and second operands */ d = dec1[i] + dec2[i] + carry; - /* Check for carry into next digit */ + /* Check for carry into next digit */ if (d > 9) { d -= 10; carry = 1; @@ -1567,7 +1569,7 @@ int carry = 0; /* Carry indicator */ /* Store digit in result */ result[i] = d; - } /* end for */ + } /* end for */ /* Check for carry out of leftmost digit */ if (carry) @@ -1576,7 +1578,7 @@ int carry = 0; /* Carry indicator */ /* Return significant digit counter */ *count = n; -} /* end function add_decimal */ +} /* end function add_decimal */ /*-------------------------------------------------------------------*/ /* Subtract two decimal byte strings as unsigned decimal numbers */ @@ -1605,8 +1607,8 @@ 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 */ +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); @@ -1619,7 +1621,7 @@ uint8 *lower; /* -> Lower value operand */ return; } - /* Point to higher and lower value operands and set sign */ + /* Point to higher and lower value operands and set sign */ if (rc > 0) { higher = dec1; lower = dec2; @@ -1651,12 +1653,12 @@ uint8 *lower; /* -> Lower value operand */ /* Store digit in result */ result[i] = d; - } /* end for */ + } /* end for */ /* Return significant digit counter */ *count = n; -} /* end function subtract_decimal */ +} /* end function subtract_decimal */ /*-------------------------------------------------------------------*/ /* Load a zoned decimal storage operand into a decimal byte string */ @@ -1688,25 +1690,25 @@ 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; + 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 */ +} /* end function load_decimal */ /*-------------------------------------------------------------------*/ /* Store decimal byte string into packed decimal storage operand */ @@ -1725,49 +1727,49 @@ int n; /* Significant digit counter */ /*-------------------------------------------------------------------*/ static void store_decimal (int32 addr, int32 len, uint8 *dec, int sign) { -int i, j, a; /* Array subscripts */ +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 */ + 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); + 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); } @@ -1776,8 +1778,8 @@ int32 cpu (int32 op, int32 m, int32 n, int32 data) int32 nulldev (int32 opcode, int32 m, int32 n, int32 data) { -if (opcode == 1) - return SCPE_OK; /* Ok to LIO unconfigured devices? */ +if (opcode == 1) + return SCPE_OK; /* Ok to LIO unconfigured devices? */ return STOP_INVDEV; } @@ -1815,10 +1817,10 @@ int32 mc = 0; uint32 i; if ((val <= 0) || (val > MAXMEMSIZE) || ((val & 07777) != 0)) - return SCPE_ARG; + 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; + return SCPE_OK; MEMSIZE = val; for (i = MEMSIZE; i < MAXMEMSIZE; i++) M[i] = 0; return SCPE_OK; diff --git a/S3/s3_defs.h b/S3/s3_defs.h index f018effa..b218e509 100644 --- a/S3/s3_defs.h +++ b/S3/s3_defs.h @@ -1,6 +1,6 @@ /* s3_defs.h: IBM System/3 simulator definitions - Copyright (c) 2001-2003, Charles E. Owen + Copyright (c) 2001-2005, 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"), @@ -19,76 +19,76 @@ 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 + 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 */ +#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 */ +#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 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 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 */ -#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 + 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 */ + 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) */ + 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 index 21d54027..d3588cfd 100644 --- a/S3/s3_disk.c +++ b/S3/s3_disk.c @@ -1,6 +1,6 @@ /* s3_disk.c: IBM 5444 Disk Drives - Copyright (c) 2001-2003, Charles E. Owen + Copyright (c) 2001-2005, 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"), @@ -19,17 +19,17 @@ 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 + 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 + 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 + 25-Apr-03 RMS Revised for extended file support + 08-Oct-02 RMS Added impossible function catcher */ #include "s3_defs.h" @@ -39,7 +39,7 @@ extern uint8 M[]; extern int32 IAR[], level; extern FILE *trace; extern int32 debug_reg; -char dbuf[DSK_SECTSIZE]; /* Disk buffer */ +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); @@ -64,113 +64,116 @@ 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 */ +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 + 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 }; +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 } }; + { 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 }; + "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 }; +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 } }; + { 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 }; + "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 }; +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 } }; + { 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 }; + "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 }; +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 } }; + { 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 }; - + "F2", &f2_unit, f2_reg, NULL, + 1, 10, 31, 1, 8, 7, + NULL, NULL, &f2_reset, + &f2_boot, &f2_attach, NULL +}; /* -------------------------------------------------------------------- */ @@ -178,436 +181,437 @@ DEVICE f2_dev = { int32 dsk1 (int32 op, int32 m, int32 n, int32 data) { - int32 r; - - r = dsk(0, op, m, n, data); - return (r); + 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); + 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); + 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) { + 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"); - } + /* 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; + /*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]; + 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++; - } + 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; - } + 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 = 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; + 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); + /* 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; + /* TIO 5444 */ + case 2: + 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); + /* 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; + /* 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 @@ -641,34 +645,34 @@ return SCPE_OK; t_stat r1_reset (DEVICE *dptr) { -diskerr[0] = notrdy[0] = seekbusy[0] = 0; /* clear indicators */ +diskerr[0] = notrdy[0] = seekbusy[0] = 0; /* clear indicators */ found[0] = 0; -sim_cancel (&r1_unit); /* clear event */ -r1_unit.u3 = 0; /* cylinder 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 */ +diskerr[0] = notrdy[0] = seekbusy[0] = 0; /* clear indicators */ found[0] = 0; -sim_cancel (&f1_unit); /* clear event */ -f1_unit.u3 = 0; /* cylinder 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 */ +diskerr[1] = notrdy[1] = seekbusy[1] = 0; /* clear indicators */ found[1] = 0; -sim_cancel (&r2_unit); /* clear event */ -r2_unit.u3 = 0; /* cylinder 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 */ +diskerr[1] = notrdy[1] = seekbusy[1] = 0; /* clear indicators */ found[1] = 0; -sim_cancel (&f2_unit); /* clear event */ -f2_unit.u3 = 0; /* cylinder 0 */ +sim_cancel (&f2_unit); /* clear event */ +f2_unit.u3 = 0; /* cylinder 0 */ return SCPE_OK; } @@ -676,30 +680,30 @@ return SCPE_OK; t_stat r1_attach (UNIT *uptr, char *cptr) { -diskerr[0] = notrdy[0] = seekbusy[0] = 0; /* clear status */ +diskerr[0] = notrdy[0] = seekbusy[0] = 0; /* clear status */ found[0] = 0; -uptr -> u3 = 0; /* cylinder 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 */ +diskerr[0] = notrdy[0] = seekbusy[0] = 0; /* clear status */ found[0] = 0; -uptr -> u3 = 0; /* cylinder 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 */ +diskerr[1] = notrdy[1] = seekbusy[1] = 0; /* clear status */ found[1] = 0; -uptr -> u3 = 0; /* cylinder 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 */ +diskerr[1] = notrdy[1] = seekbusy[1] = 0; /* clear status */ found[1] = 0; -uptr -> u3 = 0; /* cylinder 0 */ +uptr -> u3 = 0; /* cylinder 0 */ return attach_unit (uptr, cptr); } @@ -711,7 +715,7 @@ int i; r1_unit.u3 = 0; read_sector(r1_dev.units, dbuf, 0); for (i = 0; i < 256; i++) { - M[i] = dbuf[i]; + M[i] = dbuf[i]; } return SCPE_OK; } @@ -721,7 +725,7 @@ int i; f1_unit.u3 = 0; read_sector(f1_dev.units, dbuf, 0); for (i = 0; i < 256; i++) { - M[i] = dbuf[i]; + M[i] = dbuf[i]; } return SCPE_OK; } @@ -731,7 +735,7 @@ int i; r2_unit.u3 = 0; read_sector(r2_dev.units, dbuf, 0); for (i = 0; i < 256; i++) { - M[i] = dbuf[i]; + M[i] = dbuf[i]; } return SCPE_OK; } @@ -741,7 +745,7 @@ int i; f2_unit.u3 = 0; read_sector(f2_dev.units, dbuf, 0); for (i = 0; i < 256; i++) { - M[i] = dbuf[i]; + M[i] = dbuf[i]; } return SCPE_OK; } @@ -751,15 +755,15 @@ return SCPE_OK; int32 read_sector(UNIT *uptr, char *dbuf, int32 sect) { - static int32 rtn, realsect; - static long pos; + static int32 rtn, realsect; + static long pos; - /* calculate real sector no */ - if (sect > 23) - realsect = sect - 8; - else - realsect = sect; - /* physically read the sector */ + /* 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); @@ -769,17 +773,17 @@ int32 read_sector(UNIT *uptr, char *dbuf, int32 sect) int32 write_sector(UNIT *uptr, char *dbuf, int32 sect) { - static int32 rtn, realsect; - static long pos; + 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 */ + /* 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); diff --git a/S3/s3_lp.c b/S3/s3_lp.c index b643be61..cf21a127 100644 --- a/S3/s3_lp.c +++ b/S3/s3_lp.c @@ -1,6 +1,6 @@ /* s3_lp.c: IBM 1403 line printer simulator - Copyright (c) 2001-2003, Charles E. Owen + Copyright (c) 2001-2005, 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"), @@ -19,14 +19,14 @@ 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 + 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 + lpt 1403 line printer - 25-Apr-03 RMS Revised for extended file support - 08-Oct-02 RMS Added impossible function catcher + 25-Apr-03 RMS Revised for extended file support + 08-Oct-02 RMS Added impossible function catcher */ #include "s3_defs.h" @@ -43,63 +43,65 @@ 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))) +#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 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 + 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) }; +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 } }; + { 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 } }; + { 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 }; + "LPT", &lpt_unit, lpt_reg, lpt_mod, + 1, 10, 31, 1, 8, 7, + NULL, NULL, &lpt_reset, + NULL, NULL, NULL +}; /* -------------------------------------------------------------------- */ @@ -108,148 +110,151 @@ DEVICE lpt_dev = { 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; + 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 + S = suppress automatic newline */ t_stat write_line (int32 ilnt, int32 mod) { int32 i, t, lc; -static char lbuf[LPT_WIDTH + 1]; /* + null */ +static char lbuf[LPT_WIDTH + 1]; /* + null */ if ((lpt_unit.flags & UNIT_ATT) == 0) - return SCPE_UNATT; + 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++; +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; } +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 + 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) @@ -257,58 +262,62 @@ t_stat carriage_control (int32 action, int32 mod) int32 i; if ((lpt_unit.flags & UNIT_ATT) == 0) - return SCPE_UNATT; + 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; } -} +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) + count = number of lines to space or skip + sflag = skip (TRUE) or space (FALSE) */ t_stat space (int32 count, int32 sflag) @@ -316,18 +325,19 @@ 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 */ +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; + linectr -= LPFLR; return SCPE_OK; } @@ -335,8 +345,8 @@ return SCPE_OK; t_stat lpt_reset (DEVICE *dptr) { -cctptr = 0; /* clear cct ptr */ -lines = linectr = lflag = 0; /* no cc action */ +cctptr = 0; /* clear cct ptr */ +lines = linectr = lflag = 0; /* no cc action */ lpterror = 0; return SCPE_OK; } @@ -345,8 +355,8 @@ return SCPE_OK; t_stat lpt_attach (UNIT *uptr, char *cptr) { -cctptr = 0; /* clear cct ptr */ -lines = 0; /* no cc action */ +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 index 881bf360..0ba62090 100644 --- a/S3/s3_pkb.c +++ b/S3/s3_pkb.c @@ -1,6 +1,6 @@ /* s3_pkb.c: System/3 5471 console terminal simulator - Copyright (c) 2001, Charles E. Owen + Copyright (c) 2001-2005, 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"), @@ -19,14 +19,14 @@ 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 + 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 + pkb 5471 printer/keyboard - 25-Apr-03 RMS Revised for extended file support - 08-Oct-02 RMS Added impossible function catcher + 25-Apr-03 RMS Revised for extended file support + 08-Oct-02 RMS Added impossible function catcher */ #include "s3_defs.h" @@ -39,56 +39,59 @@ 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 + 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 */ +#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 */ +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 } }; + { 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 } }; + { 0 } +}; DEVICE pkb_dev = { - "PKB", &pkb_unit, pkb_reg, pkb_mod, - 1, 10, 31, 1, 8, 8, - NULL, NULL, &pkb_reset, - NULL, NULL, NULL }; + "PKB", &pkb_unit, pkb_reg, pkb_mod, + 1, 10, 31, 1, 8, 8, + NULL, NULL, &pkb_reset, + NULL, NULL, NULL +}; /*-------------------------------------------------------------------*/ @@ -141,97 +144,97 @@ unsigned char ascii_to_ebcdic[] = { 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; + 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 */ @@ -240,58 +243,58 @@ t_stat pkb_svc (UNIT *uptr) { int32 temp, ac, ec; -sim_activate (&pkb_unit, pkb_unit.wait); /* continue poll */ +sim_activate (&pkb_unit, pkb_unit.wait); /* continue poll */ -if (pkb_unit.u3 & PRT_INTREQ) { /* Printer Interrupt */ - int_req |= 2; - return SCPE_OK; -} +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? */ +if ((temp = sim_poll_kbd ()) < SCPE_KFLAG) return temp; /* no char or error? */ -ac = temp & 0x7f; /* placed type ASCII char in ac */ +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 (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 */ + 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_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_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 (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 */ -} +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; } @@ -300,8 +303,8 @@ return SCPE_OK; 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 */ +int_req = int_req & ~0x02; /* reset interrupt */ +sim_activate (&pkb_unit, pkb_unit.wait); /* activate unit */ return SCPE_OK; } diff --git a/S3/s3_sys.c b/S3/s3_sys.c index 4f4eed62..0fa2c1ee 100644 --- a/S3/s3_sys.c +++ b/S3/s3_sys.c @@ -1,6 +1,6 @@ /* s3_sys.c: IBM System/3 system interface - Copyright (c) 2001-2003, Charles E. Owen + Copyright (c) 2001-2005, 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"), @@ -19,8 +19,8 @@ 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 + 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. */ @@ -45,16 +45,16 @@ 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, uint32 *val, - UNIT *uptr, int32 sw); + 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 + 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"; @@ -63,17 +63,19 @@ 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 }; +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", @@ -94,125 +96,127 @@ const char *sim_stop_messages[] = { 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 + 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) + 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. + 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 + "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)" }; +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 @@ -226,43 +230,43 @@ 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 */ + 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 + *of = output stream + addr = current PC + *val = pointer to values + *uptr = pointer to unit + sw = switches Outputs: - status = error code + status = error code */ int32 fprint_sym (FILE *of, int32 addr, uint32 *val, - UNIT *uptr, int32 sw) + 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 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, uint32 *val, - UNIT *uptr, int32 sw) + UNIT *uptr, int32 sw) { int32 cflag, c1, c2, group, len1, len2, inst, aaddr, baddr; int32 oplen, groupno, i, j, vpos, qbyte, da, m, n; @@ -273,40 +277,40 @@ 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; } + 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; } + 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; @@ -318,182 +322,182 @@ qbyte = val[1]; /* Get total length of instruction */ if (group == 0x0f) { - oplen = 3; + 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++; + 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; -} + 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; - } + 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; + sprintf(strg, "%02X", val[0]); + oplen = 1; } else { - sprintf(bld, "%s ", opcode[i].op); + sprintf(bld, "%s ", opcode[i].op); - /* Extract the addresses into aaddr and baddr */ + /* 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; - } + 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 */ + /* Display the operands in the correct format */ - da = (qbyte >> 4) & 0x0f; - m = (qbyte >> 3) & 0x01; - n = (qbyte) & 0x07; + 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); + 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 + *cptr = pointer to input string + addr = current PC + *uptr = pointer to unit + *val = pointer to output values + sw = switches Outputs: - status = error status + status = error status */ int32 parse_sym (char *cptr, int32 addr, UNIT *uptr, uint32 *val, int32 sw) @@ -502,25 +506,27 @@ 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 */ +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 (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; } + 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); + if (*cptr == ',' || *cptr == '\0' || *cptr == '(' || + isdigit(*cptr)) + break; + gbuf[i] = toupper(*cptr); cptr++; i++; } @@ -528,388 +534,388 @@ while (1) { /* kill trailing spaces if any */ gbuf[i] = '\0'; for (j = i - 1; gbuf[j] == ' '; j--) { - gbuf[j] = '\0'; + gbuf[j] = '\0'; } /* find opcode in table */ for (j = 0; j < nopcode; j++) { - if (strcmp(gbuf, opcode[j].op) == 0) - break; + if (strcmp(gbuf, opcode[j].op) == 0) + break; } -if (j >= nopcode) /* not found */ - return SCPE_ARG; +if (j >= nopcode) /* not found */ + return SCPE_ARG; -oplen = 2; /* start with op & q */ +oplen = 2; /* start with op & q */ -val[0] = opcode[j].opmask; /* store opcode right nybble */ +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; +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; } @@ -922,19 +928,19 @@ 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; +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/SDS/sds_cpu.c b/SDS/sds_cpu.c index 353a83b3..038dca10 100644 --- a/SDS/sds_cpu.c +++ b/SDS/sds_cpu.c @@ -1,6 +1,6 @@ /* sds_cpu.c: SDS 940 CPU simulator - Copyright (c) 2001-2004, Robert M. Supnik + Copyright (c) 2001-2005, 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"), @@ -19,34 +19,34 @@ 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 + 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 - rtc real time clock + cpu central processor + rtc real time clock - 07-Nov-04 RMS Added instruction history - 01-Mar-03 RMS Added SET/SHOW RTC FREQ support + 16-Aug-05 RMS Fixed C++ declaration and cast problems + 07-Nov-04 RMS Added instruction history + 01-Mar-03 RMS Added SET/SHOW RTC FREQ support 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 -*/ - -/* The SDS 940 has three instruction format -- memory reference, register change, + 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 + + 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 @@ -54,22 +54,22 @@ | 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 + 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 + 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: @@ -84,9 +84,8 @@ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | 0|CH| 0| opcode |mode | I/O function | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ -*/ - -/* This routine is the instruction decode routine for the SDS 940. + + 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. @@ -95,24 +94,24 @@ 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 + 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) + 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 @@ -125,74 +124,76 @@ 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 + 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) +#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) -#define HIST_XCT 1 /* instruction */ -#define HIST_INT 2 /* interrupt cycle */ -#define HIST_TRP 3 /* trap cycle */ -#define HIST_MIN 64 -#define HIST_MAX 65536 -#define HIST_NOEA 0x40000000 -struct InstHistory { - uint32 typ; - uint32 pc; - uint32 ir; - uint32 a; - uint32 b; - uint32 x; - uint32 ea; }; +#define HIST_XCT 1 /* instruction */ +#define HIST_INT 2 /* interrupt cycle */ +#define HIST_TRP 3 /* trap cycle */ +#define HIST_MIN 64 +#define HIST_MAX 65536 +#define HIST_NOEA 0x40000000 -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 hst_p = 0; /* history pointer */ -int32 hst_lnt = 0; /* history length */ -struct InstHistory *hst = NULL; /* instruction history */ -int32 rtc_pie = 0; /* rtc pulse ie */ -int32 rtc_tps = 60; /* rtc ticks/sec */ +typedef struct { + uint32 typ; + uint32 pc; + uint32 ir; + uint32 a; + uint32 b; + uint32 x; + uint32 ea; + } InstHistory; + +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 hst_p = 0; /* history pointer */ +int32 hst_lnt = 0; /* history length */ +InstHistory *hst = NULL; /* instruction history */ +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 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); @@ -230,123 +231,131 @@ 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 + 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 } }; + { 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 }, - { MTAB_XTD|MTAB_VDV|MTAB_NMO|MTAB_SHP, 0, "HISTORY", "HISTORY", - &cpu_set_hist, &cpu_show_hist }, - { 0 } }; + { 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 }, + { MTAB_XTD|MTAB_VDV|MTAB_NMO|MTAB_SHP, 0, "HISTORY", "HISTORY", + &cpu_set_hist, &cpu_show_hist }, + { 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 }; - + "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 + 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 } }; + { 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 } }; + { 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 }; + "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 }; + 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 }; - + 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; @@ -355,105 +364,115 @@ t_stat reason, tr; /* Restore register state */ -if (io_init ()) return SCPE_STOP; /* init IO; conflict? */ +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 */ +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 */ +while (reason == 0) { /* loop until halted */ -if (cpu_astop) { /* debug stop? */ - cpu_astop = 0; - return SCPE_STOP; } + 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 (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 */ - } + 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 (hst_lnt) inst_hist (tinst, P, HIST_INT); /* record inst */ - 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 */ - if (hst_lnt) inst_hist (inst, save_P, HIST_XCT); - 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; - if (hst_lnt) inst_hist (tinst, save_P, HIST_TRP); - 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 */ + 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 (hst_lnt) inst_hist (tinst, P, HIST_INT); /* record inst */ + 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 */ + if (hst_lnt) inst_hist (inst, save_P, HIST_XCT); + 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; + if (hst_lnt) inst_hist (tinst, save_P, HIST_TRP); + 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 */ +pcq_r->qptr = pcq_p; /* update pc q ptr */ return reason; } - + /* Simulate one instruction */ t_stat one_inst (uint32 inst, uint32 pc, uint32 mode) @@ -463,415 +482,475 @@ uint32 old_A, old_B, old_X; int32 i, exu_cnt, sc; t_stat r; -exu_cnt = 0; /* init EXU count */ +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 */ - +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; - + 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; - + 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; - + 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; - + 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; + 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; - + 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 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; -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; } + 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 */ +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) { /* end of ind chain? */ - if (hst_lnt) hst[hst_p].ea = *addr; /* record */ - return SCPE_OK; } - if (r = Read (va, &wd)) return r; /* read ind; fails? */ - va = (va & VA_USR) | (wd & XVA_MASK); - } -return STOP_INDLIM; /* too many indirects */ +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) { /* end of ind chain? */ + if (hst_lnt) hst[hst_p].ea = *addr; /* record */ + return SCPE_OK; + } + 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 */ @@ -879,22 +958,23 @@ return STOP_INDLIM; /* too many indirects */ t_stat EaSh (uint32 inst, uint32 *addr) { int32 i; -uint32 wd = inst; /* homeable */ -uint32 va = wd & XVA_MASK; /* initial va */ +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; - if (hst_lnt) hst[hst_p].ea = *addr; /* record */ - 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 */ +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; + if (hst_lnt) hst[hst_p].ea = *addr; /* record */ + 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 */ @@ -903,21 +983,25 @@ 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 */ +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; } @@ -927,22 +1011,27 @@ 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 (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; } @@ -954,37 +1043,40 @@ 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 */ +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 */ +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> */ +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 */ +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 */ +uint32 t = s1 + s2; /* add */ +if (((s1 ^ ~s2) & (s1 ^ t)) & SIGN) OV = 1; /* overflow */ return t & DMASK; } @@ -994,21 +1086,23 @@ 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 */ +if ((a == 0) || (b == 0)) { /* ops zero? */ + A = B = 0; + return; + } +t = a >> 12; /* split op1 */ a = a & 07777; -u = b >> 12; /* split op2 */ +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 */ +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; } + B = ((B ^ DMASK) + 1) & DMASK; + A = ((A ^ DMASK) + (B == 0)) & DMASK; + } else if (A & SIGN) OV = 1; return; } @@ -1022,32 +1116,34 @@ return; 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 */ +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? */ +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 */ +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; } @@ -1056,11 +1152,14 @@ 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; } + 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; } @@ -1068,14 +1167,17 @@ 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; } + 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) @@ -1138,10 +1240,11 @@ 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 */ +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 */ @@ -1150,18 +1253,20 @@ 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 */ +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) @@ -1220,10 +1325,10 @@ int32 mc = 0; uint32 i; if ((val <= 0) || (val > MAXMEMSIZE) || ((val & 037777) != 0)) - return SCPE_ARG; + 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; + return SCPE_OK; MEMSIZE = val; for (i = MEMSIZE; i < MAXMEMSIZE; i++) M[i] = 0; return SCPE_OK; @@ -1239,19 +1344,22 @@ 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); } +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 @@ -1260,8 +1368,8 @@ return SCPE_OK; 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 */ +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; } @@ -1272,15 +1380,15 @@ 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 */ +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; } @@ -1288,8 +1396,8 @@ return SCPE_OK; t_stat rtc_reset (DEVICE *dptr) { -rtc_pie = 0; /* disable pulse */ -sim_activate (&rtc_unit, rtc_unit.wait); /* activate unit */ +rtc_pie = 0; /* disable pulse */ +sim_activate (&rtc_unit, rtc_unit.wait); /* activate unit */ return SCPE_OK; } @@ -1315,7 +1423,7 @@ return SCPE_OK; void inst_hist (uint32 ir, uint32 pc, uint32 tp) { -hst_p = (hst_p + 1); /* next entry */ +hst_p = (hst_p + 1); /* next entry */ if (hst_p >= hst_lnt) hst_p = 0; hst[hst_p].typ = tp | (OV << 4); hst[hst_p].pc = pc; @@ -1335,20 +1443,23 @@ int32 i, lnt; t_stat r; if (cptr == NULL) { - for (i = 0; i < hst_lnt; i++) hst[i].typ = 0; - hst_p = 0; - return SCPE_OK; } + for (i = 0; i < hst_lnt; i++) hst[i].typ = 0; + hst_p = 0; + return SCPE_OK; + } lnt = (int32) get_uint (cptr, 10, HIST_MAX, &r); if ((r != SCPE_OK) || (lnt && (lnt < HIST_MIN))) return SCPE_ARG; hst_p = 0; if (hst_lnt) { - free (hst); - hst_lnt = 0; - hst = NULL; } + free (hst); + hst_lnt = 0; + hst = NULL; + } if (lnt) { - hst = calloc (sizeof (struct InstHistory), lnt); - if (hst == NULL) return SCPE_MEM; - hst_lnt = lnt; } + hst = (InstHistory *) calloc (lnt, sizeof (InstHistory)); + if (hst == NULL) return SCPE_MEM; + hst_lnt = lnt; + } return SCPE_OK; } @@ -1360,32 +1471,33 @@ int32 ov, k, di, lnt; char *cptr = (char *) desc; t_stat r; t_value sim_eval; -struct InstHistory *h; +InstHistory *h; extern t_stat fprint_sym (FILE *ofile, t_addr addr, t_value *val, - UNIT *uptr, int32 sw); + UNIT *uptr, int32 sw); static char *cyc[] = { " ", " ", "INT", "TRP" }; -if (hst_lnt == 0) return SCPE_NOFNC; /* enabled? */ +if (hst_lnt == 0) return SCPE_NOFNC; /* enabled? */ if (cptr) { - lnt = (int32) get_uint (cptr, 10, hst_lnt, &r); - if ((r != SCPE_OK) || (lnt == 0)) return SCPE_ARG; } + lnt = (int32) get_uint (cptr, 10, hst_lnt, &r); + if ((r != SCPE_OK) || (lnt == 0)) return SCPE_ARG; + } else lnt = hst_lnt; -di = hst_p - lnt; /* work forward */ +di = hst_p - lnt; /* work forward */ if (di < 0) di = di + hst_lnt; fprintf (st, "CYC PC OV A B X EA IR\n\n"); -for (k = 0; k < lnt; k++) { /* print specified */ - h = &hst[(++di) % hst_lnt]; /* entry pointer */ - if (h->typ) { /* instruction? */ - ov = (h->typ >> 4) & 1; /* overflow */ - fprintf (st, "%s %05o %o %08o %08o %08o ", cyc[h->typ & 3], - h->pc, ov, h->a, h->b, h->x); - if (h->ea & HIST_NOEA) fprintf (st, " "); - else fprintf (st, "%05o ", h->ea); - sim_eval = h->ir; - if ((fprint_sym (st, h->pc, &sim_eval, &cpu_unit, SWMASK ('M'))) > 0) - fprintf (st, "(undefined) %08o", h->ir); - fputc ('\n', st); /* end line */ - } /* end else instruction */ - } /* end for */ +for (k = 0; k < lnt; k++) { /* print specified */ + h = &hst[(++di) % hst_lnt]; /* entry pointer */ + if (h->typ) { /* instruction? */ + ov = (h->typ >> 4) & 1; /* overflow */ + fprintf (st, "%s %05o %o %08o %08o %08o ", cyc[h->typ & 3], + h->pc, ov, h->a, h->b, h->x); + if (h->ea & HIST_NOEA) fprintf (st, " "); + else fprintf (st, "%05o ", h->ea); + sim_eval = h->ir; + if ((fprint_sym (st, h->pc, &sim_eval, &cpu_unit, SWMASK ('M'))) > 0) + fprintf (st, "(undefined) %08o", h->ir); + fputc ('\n', st); /* end line */ + } /* end else instruction */ + } /* end for */ return SCPE_OK; } diff --git a/SDS/sds_defs.h b/SDS/sds_defs.h index aacdd26c..4b715f15 100644 --- a/SDS/sds_defs.h +++ b/SDS/sds_defs.h @@ -1,6 +1,6 @@ /* sds_defs.h: SDS 940 simulator definitions - Copyright (c) 2001-2004, Robert M. Supnik + Copyright (c) 2001-2005, 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"), @@ -19,377 +19,381 @@ 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 + 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 + 25-Apr-03 RMS Revised for extended file support */ -#include "sim_defs.h" /* simulator defns */ +#ifndef _SDS_DEFS_H_ +#define _SDS_DEFS_H_ 0 + +#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 */ +#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 */ +#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) +#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))) +#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 +#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) +#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)) +#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 */ +#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)) +#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) +#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 */ +#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 */ +#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 */ - }; + 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); - }; + 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 +#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) +#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) +#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 */ +#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_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 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" */ +#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 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 */ +#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_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) +#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 */ +#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 }; + 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 */ @@ -401,3 +405,5 @@ 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); + +#endif diff --git a/SDS/sds_doc.txt b/SDS/sds_doc.txt index 62e18a40..55b27e47 100644 --- a/SDS/sds_doc.txt +++ b/SDS/sds_doc.txt @@ -1,14 +1,14 @@ To: Users From: Bob Supnik Subj: SDS 940 Simulator Usage -Date: 15-Nov-2004 +Date: 01-Jul-2005 COPYRIGHT NOTICE The following copyright notice applies to both the SIMH source and binary: - Original code published in 1993-2004, written by Robert M Supnik - Copyright (c) 1993-2004, Robert M Supnik + Original code published in 1993-2005, written by Robert M Supnik + Copyright (c) 1993-2005, 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"), @@ -27,8 +27,8 @@ The following copyright notice applies to both the SIMH source and binary: 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 + 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. @@ -367,8 +367,7 @@ 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. +active connections. The SET MUXLn DISCONNECT command disconnects line n. The controller (MUX) implements these registers: diff --git a/SDS/sds_drm.c b/SDS/sds_drm.c index 825f4d67..01545bb1 100644 --- a/SDS/sds_drm.c +++ b/SDS/sds_drm.c @@ -1,6 +1,6 @@ /* sds_drm.c: SDS 940 Project Genie drum simulator - Copyright (c) 2002-2004, Robert M. Supnik + Copyright (c) 2002-2005, 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"), @@ -19,11 +19,11 @@ 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 + 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 + drm drum The drum is buffered in memory. @@ -43,65 +43,65 @@ /* 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_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_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_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 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 */ +#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 */ +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); @@ -110,37 +110,40 @@ t_stat drm_reset (DEVICE *dptr); /* DRM data structures - drm_dev device descriptor - drm_unit unit descriptor - drm_reg register list + 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) }; +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 } }; + { 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 }; - + "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) @@ -148,31 +151,36 @@ 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; + 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; + } -default: - return SCPE_IERR; } /* can't get here */ return SCPE_OK; } - + /* Unit service */ t_stat drm_svc (UNIT *uptr) @@ -181,91 +189,105 @@ int32 t, rda; uint32 dpc, dwd; uint32 *fbuf = uptr->filebuf; -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 */ +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 */ - fbuf[drm_da] = dwd; /* write to drum */ - if (drm_da >= uptr->hwmark) uptr->hwmark = drm_da + 1; } - else { /* read */ - dwd = fbuf[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 */ + 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 */ + fbuf[drm_da] = dwd; /* write to drum */ + if (drm_da >= uptr->hwmark) uptr->hwmark = drm_da + 1; + } + else { /* read */ + dwd = fbuf[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 (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? */ - M[drm_da] = drm_par << 12; /* clobber data */ - if (drm_da >= uptr->hwmark) uptr->hwmark = drm_da + 1; } + if ((drm_da & DRM_M_WD) && drm_rw) { /* wr end mid sector? */ + M[drm_da] = drm_par << 12; /* clobber data */ + 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 */ + 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_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 */ +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 index ae303ede..8165f500 100644 --- a/SDS/sds_dsk.c +++ b/SDS/sds_dsk.c @@ -1,6 +1,6 @@ /* sds_dsk.c: SDS 940 moving head disk simulator - Copyright (c) 2001-2004, Robert M. Supnik + Copyright (c) 2001-2005, 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"), @@ -19,70 +19,73 @@ 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 + 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 + 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 + <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 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)) -#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_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 } }; +DSPT dsk_tplt[] = { /* template */ + { 1, 0 }, + { 1, DEV_OUT }, + { 0, 0 } + }; DEVICE dsk_dev; t_stat dsk_svc (UNIT *uptr); @@ -95,52 +98,54 @@ t_stat dsk (uint32 fnc, uint32 inst, uint32 *dat); /* DSK data structures - dsk_dev device descriptor - dsk_unit unit descriptor - dsk_reg register list + 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) }; +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 } }; + { 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 } }; + { 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 }; - + "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 + 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) @@ -148,79 +153,84 @@ 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; +switch (fnc) { /* case on function */ -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_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_DISC: /* disconnect */ - dsk_end_op (0); /* normal term */ - if (inst & DEV_OUT) return dsk_fill (inst); /* fill write */ - 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_WREOR: /* write eor */ - dsk_end_op (CHF_EOR); /* eor term */ - return dsk_fill (inst); /* fill write */ + case IO_DISC: /* disconnect */ + dsk_end_op (0); /* normal term */ + if (inst & DEV_OUT) return dsk_fill (inst); /* fill write */ + break; -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_WREOR: /* write eor */ + dsk_end_op (CHF_EOR); /* eor term */ + return dsk_fill (inst); /* fill write */ -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_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_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; + 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; -default: - CRETINS; } -return SCPE_OK; + 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 */ +*dat = dsk_da; /* ret disk addr */ return SCPE_OK; } @@ -230,13 +240,13 @@ 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 */ +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 */ +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; } @@ -244,12 +254,14 @@ return SCPE_OK; 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 */ +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 */ + xfr_req = xfr_req | XFR_DSK; /* set xfr req */ + sim_activate (&dsk_unit, dsk_time); /* activate */ + } return SCPE_OK; } @@ -259,20 +271,22 @@ 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); } +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 */ +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; } +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 */ +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; } @@ -286,21 +300,24 @@ 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; } +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 */ +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 */ +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; } @@ -310,48 +327,50 @@ return SCPE_OK; 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 */ +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 */ +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 */ + 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 */ +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 */ +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 */ +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 */ +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 index 0298a659..11a057a2 100644 --- a/SDS/sds_io.c +++ b/SDS/sds_io.c @@ -1,6 +1,6 @@ /* sds_io.c: SDS 940 I/O simulator - Copyright (c) 2001-2004, Robert M. Supnik + Copyright (c) 2001-2005, 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"), @@ -19,8 +19,8 @@ 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 + 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. */ @@ -28,55 +28,56 @@ /* Data chain word */ -#define CHD_INT 040 /* int on chain */ -#define CHD_PAGE 037 /* new page # */ +#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) +#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 */ +#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 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))) +#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" }; +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 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; @@ -108,7 +109,7 @@ 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 @@ -150,64 +151,69 @@ extern void set_dyn_map (void); 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 */ - }; - + 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 + 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 } }; + { 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 } }; + { 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 }; - + "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 }; + 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 }; + 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 */ @@ -224,39 +230,41 @@ 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 } }; - + { 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 */ +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; } @@ -264,178 +272,203 @@ 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 */ +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 */ +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 */ +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 */ +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 */ +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 # */ +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 */ + + 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? */ + 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 # */ +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 ((ch == 4) && !(inst & 037774)) { /* EM test */ if (((inst & 0001) && (EM2 != 2)) || - ((inst & 0002) && (EM3 != 3))) *dat = 1; - return SCPE_OK; } + ((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 */ + + 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) @@ -474,35 +507,36 @@ return SCPE_OK; t_stat pot_fork (uint32 num, uint32 *dat) { -uint32 igrp = SYI_GETGRP (*dat); /* get group */ -uint32 fbit = (1 << (VEC_FORK & 017)); /* bit in group */ +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; } +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 + 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; @@ -510,57 +544,60 @@ 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; +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; + 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 */ +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; } @@ -571,25 +608,26 @@ 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; + 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; } + 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 + 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) { @@ -598,74 +636,80 @@ 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? */ +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 */ +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 */ +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; } @@ -676,12 +720,12 @@ 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 */ +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 */ + 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; } @@ -689,7 +733,7 @@ return SCPE_OK; t_stat dev_disc (uint32 ch, uint32 dev) { -chan_uar[ch] = 0; /* disconnect */ +chan_uar[ch] = 0; /* disconnect */ if (dev_dsp[dev][ch]) return dev_dsp[dev][ch] (IO_DISC, dev, NULL); return SCPE_OK; } @@ -697,10 +741,10 @@ 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 */ +chan_flag[ch] = chan_flag[ch] | CHF_EOR; /* set eor */ return SCPE_OK; } - + /* Externally visible routines */ /* Channel driver */ @@ -709,12 +753,14 @@ 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; } } +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; } @@ -726,7 +772,8 @@ 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; } + if ((dev && TST_XFR (dev, i)) || TST_EOR (i)) return 1; + } return 0; } @@ -735,10 +782,11 @@ return 0; 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 */ + 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; } @@ -782,7 +830,8 @@ for (i = 0; i < NUM_CHAN; i++) { chan_cpw[i] = 0; chan_cnt[i] = 0; chan_mode[i] = 0; - chan_flag[i] = 0; } + chan_flag[i] = 0; + } return SCPE_OK; } @@ -794,17 +843,19 @@ DEVICE *dptr; DIB *dibp; int32 i; -if (sptr == NULL) return SCPE_ARG; /* valid args? */ +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; } } +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; } @@ -835,36 +886,39 @@ 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; } } + 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 */ +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 */ + 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; } @@ -873,14 +927,14 @@ return FALSE; 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]); +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 index 880cfe11..b419e00d 100644 --- a/SDS/sds_lp.c +++ b/SDS/sds_lp.c @@ -1,6 +1,6 @@ /* sds_lp.c: SDS 940 line printer simulator - Copyright (c) 2001-2004, Robert M. Supnik + Copyright (c) 2001-2005, 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"), @@ -19,40 +19,43 @@ 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 + 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 + lpt line printer - 25-Apr-03 RMS Revised for extended file support + 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 */ +#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 */ +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[] = { /* template */ + { 1, 0 }, + { 0, 0 } + }; DEVICE lpt_dev; t_stat lpt_svc (UNIT *uptr); @@ -63,57 +66,61 @@ 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 + 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) }; + 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 } }; + { 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 } }; + { 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 }; - + "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 + 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. @@ -124,81 +131,89 @@ 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; +switch (fnc) { /* case function */ -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_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_DISC: /* disconnect */ - lpt_end_op (0); /* normal term */ - return lpt_bufout (&lpt_unit); /* dump output */ + 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_WREOR: /* write eor */ - lpt_sta = (lpt_sta | SET_EOR) & ~SET_XFR; /* need eor */ - sim_activate (&lpt_unit, lpt_ptime); /* start timer */ - break; + case IO_DISC: /* disconnect */ + lpt_end_op (0); /* normal term */ + return lpt_bufout (&lpt_unit); /* dump output */ -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_WREOR: /* write eor */ + lpt_sta = (lpt_sta | SET_EOR) & ~SET_XFR; /* need eor */ + sim_activate (&lpt_unit, lpt_ptime); /* start timer */ + 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; + 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; + } -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" }; + "\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 */ +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; } @@ -208,28 +223,32 @@ t_stat lpt_bufout (UNIT *uptr) { int32 i; -if ((uptr->flags & UNIT_ATT) && lpt_bptr) { /* attached? */ +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 */ + 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 */ +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 */ + lpt_end_op (CHF_EOR | CHF_ERR); /* set err, disc */ + CRETIOE (lpt_stopioe, SCPE_UNATT); /* ret error */ + } return SCPE_OK; } @@ -237,12 +256,13 @@ return SCPE_OK; 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 */ +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; } @@ -252,27 +272,30 @@ 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 */ +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 */ +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 */ +xfr_req = xfr_req & ~XFR_LPT; /* clr xfr flag */ +sim_cancel (&lpt_unit); /* deactivate */ return SCPE_OK; } @@ -280,6 +303,6 @@ return SCPE_OK; t_stat lpt_attach (UNIT *uptr, char *cptr) { -lpt_ccp = 0; /* top of form */ +lpt_ccp = 0; /* top of form */ return attach_unit (uptr, cptr); } diff --git a/SDS/sds_mt.c b/SDS/sds_mt.c index 60982272..1a339243 100644 --- a/SDS/sds_mt.c +++ b/SDS/sds_mt.c @@ -1,6 +1,6 @@ /* sds_mt.c: SDS 940 magnetic tape simulator - Copyright (c) 2001-2004, Robert M. Supnik + Copyright (c) 2001-2005, 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"), @@ -19,27 +19,27 @@ 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 + 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 + mt 7 track magnetic tape - 07-Dec-04 RMS Added read-only file support - 25-Apr-03 RMS Revised for extended file support - 28-Mar-03 RMS Added multiformat support - 28-Feb-03 RMS Revised for magtape library + 07-Dec-04 RMS Added read-only file support + 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 + 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. @@ -49,28 +49,31 @@ #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 */ +#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 } }; +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); @@ -86,219 +89,234 @@ 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 }; + 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 }; - + 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 + 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_ROABLE +UNIT_DISABLE, 0) }, - { UDATA (&mt_svc, UNIT_ATTABLE + UNIT_ROABLE +UNIT_DISABLE, 0) }, - { UDATA (&mt_svc, UNIT_ATTABLE + UNIT_ROABLE +UNIT_DISABLE, 0) }, - { UDATA (&mt_svc, UNIT_ATTABLE + UNIT_ROABLE +UNIT_DISABLE, 0) }, - { UDATA (&mt_svc, UNIT_ATTABLE + UNIT_ROABLE +UNIT_DISABLE, 0) }, - { UDATA (&mt_svc, UNIT_ATTABLE + UNIT_ROABLE +UNIT_DISABLE, 0) }, - { UDATA (&mt_svc, UNIT_ATTABLE + UNIT_ROABLE +UNIT_DISABLE, 0) }, - { UDATA (&mt_svc, UNIT_ATTABLE + UNIT_ROABLE +UNIT_DISABLE, 0) } }; + { UDATA (&mt_svc, UNIT_ATTABLE + UNIT_ROABLE + UNIT_DISABLE, 0) }, + { UDATA (&mt_svc, UNIT_ATTABLE + UNIT_ROABLE + UNIT_DISABLE, 0) }, + { UDATA (&mt_svc, UNIT_ATTABLE + UNIT_ROABLE + UNIT_DISABLE, 0) }, + { UDATA (&mt_svc, UNIT_ATTABLE + UNIT_ROABLE + UNIT_DISABLE, 0) }, + { UDATA (&mt_svc, UNIT_ATTABLE + UNIT_ROABLE + UNIT_DISABLE, 0) }, + { UDATA (&mt_svc, UNIT_ATTABLE + UNIT_ROABLE + UNIT_DISABLE, 0) }, + { UDATA (&mt_svc, UNIT_ATTABLE + UNIT_ROABLE + UNIT_DISABLE, 0) }, + { UDATA (&mt_svc, UNIT_ATTABLE + UNIT_ROABLE + 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 } }; + { 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 } }; + { 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 }; - + "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 + 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 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; +switch (fnc) { /* case function */ -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_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_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_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_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_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_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_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_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_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_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; + 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; -default: - CRETINS; } + 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 */ +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; } @@ -307,26 +325,29 @@ return SCPE_OK; t_stat mt_readrec (UNIT *uptr) { t_mtrlnt tbc; -t_stat st, r = SCPE_OK; +t_stat st; -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 */ +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; } @@ -334,16 +355,17 @@ return SCPE_OK; 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? */ +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 */ + 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) @@ -352,40 +374,42 @@ 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 */ +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 */ + 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_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 */ +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 */ @@ -394,17 +418,18 @@ t_stat mt_reset (DEVICE *dptr) { int32 i; -chan_disc (mt_dib.chan); /* disconnect */ -mt_eof = 0; /* clear state */ +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 */ +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; } + mt_unit[i].eotf = 0; + } return SCPE_OK; } @@ -433,12 +458,12 @@ 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 */ +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 index 0c52473b..3d8fe909 100644 --- a/SDS/sds_mux.c +++ b/SDS/sds_mux.c @@ -1,6 +1,6 @@ /* sds_mux.c: SDS 940 terminal multiplexor simulator - Copyright (c) 2001-2004, Robert M Supnik + Copyright (c) 2001-2005, 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"), @@ -19,14 +19,16 @@ 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 + 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 + mux terminal multiplexor - 05-Jan-04 RMS Revised for tmxr library changes - 09-May-03 RMS Added network device flag + 29-Jun-05 RMS Added SET MUXLn DISCONNECT + 21-Jun-05 RMS Fixed bug in SHOW CONN/STATS + 05-Jan-04 RMS Revised for tmxr library changes + 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. @@ -37,80 +39,81 @@ #include "sim_tmxr.h" #include -#define PROJ_GENIE (cpu_unit.flags & UNIT_GENIE) -#define MUX_NUMLIN mux_desc.lines +#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)) +#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) +#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) +#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) +#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 */ +#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 */ - +#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 */ +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, mux_ldsc }; /* mux descriptor */ +TMLN mux_ldsc[MUX_LINES] = { 0 }; /* line descriptors */ +TMXR mux_desc = { MUX_LINES, 0, 0, mux_ldsc }; /* mux descriptor */ t_stat mux (uint32 fnc, uint32 inst, uint32 *dat); t_stat muxi_svc (UNIT *uptr); @@ -123,13 +126,13 @@ 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 + 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 }; @@ -139,97 +142,106 @@ 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 } }; + { 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 } }; + { 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 }; + "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 + 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 } }; + { 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 }, - { MTAB_XTD|MTAB_VUN|MTAB_NC, 0, "LOG", "LOG", - &tmxr_set_log, &tmxr_show_log, &mux_desc }, - { MTAB_XTD|MTAB_VUN|MTAB_NC, 0, NULL, "NOLOG", - &tmxr_set_nolog, NULL, &mux_desc }, - { 0 } }; + { UNIT_UC, 0, "lower case", "LC", NULL }, + { UNIT_UC, UNIT_UC, "upper case", "UC", NULL }, + { MTAB_XTD|MTAB_VUN, 0, NULL, "DISCONNECT", + &tmxr_dscln, NULL, &mux_desc }, + { MTAB_XTD|MTAB_VUN|MTAB_NC, 0, "LOG", "LOG", + &tmxr_set_log, &tmxr_show_log, &mux_desc }, + { MTAB_XTD|MTAB_VUN|MTAB_NC, 0, NULL, "NOLOG", + &tmxr_set_nolog, NULL, &mux_desc }, + { 0 } + }; REG muxl_reg[] = { - { URDATA (TIME, muxl_unit[0].wait, 10, 24, 0, - MUX_LINES, REG_NZ + PV_LEFT) }, - { NULL } }; + { 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 }; - + "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 */ @@ -239,25 +251,32 @@ 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 */ + + 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; } @@ -268,15 +287,16 @@ 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 */ +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; } @@ -285,29 +305,34 @@ 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_linemsg (&mux_ldsc[ln], "\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 (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_linemsg (&mux_ldsc[ln], "\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; } + 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 @@ -318,31 +343,35 @@ 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 */ +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; } @@ -351,22 +380,26 @@ return SCPE_OK; t_stat muxo_svc (UNIT *uptr) { int32 c; -uint32 ln = uptr - muxl_unit; /* line # */ +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_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 */ + MUX_SETFLG (ln, MUX_FXMT); /* set flag */ + mux_scan_next (); /* kick scanner */ + } return SCPE_OK; } @@ -376,33 +409,36 @@ 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; } +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 */ +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 (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 */ + 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_reset_ln (i); -for (i = 0; i < MUX_FLAGS; i++) MUX_CLRINT (i); /* clear all ints */ +for (i = 0; i < MUX_FLAGS; i++) MUX_CLRINT (i); /* clear all ints */ return SCPE_OK; } @@ -413,10 +449,10 @@ 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 */ +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 */ +sim_activate (uptr, t); /* start poll */ return SCPE_OK; } @@ -427,9 +463,9 @@ 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 */ +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; } @@ -449,14 +485,17 @@ return SCPE_OK; t_stat mux_show (FILE *st, UNIT *uptr, int32 val, void *desc) { -int32 i; +int32 i, t; -for (i = 0; (i < MUX_LINES) && (mux_ldsc[i].conn == 0); i++) ; -if (i < MUX_LINES) { +for (i = t = 0; i < MUX_LINES; i++) t = t + (mux_ldsc[i].conn != 0); +if (t) { 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); } } + 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; } @@ -475,18 +514,21 @@ 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; + return SCPE_OK; for (i = newln; i < MUX_NUMLIN; i++) { - if (mux_ldsc[i].conn) { - tmxr_linemsg (&mux_ldsc[i], "\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); } + if (mux_ldsc[i].conn) { + tmxr_linemsg (&mux_ldsc[i], "\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); } + muxl_unit[i].flags = muxl_unit[i].flags & ~UNIT_DIS; + mux_reset_ln (i); + } } MUX_NUMLIN = newln; return SCPE_OK; diff --git a/SDS/sds_rad.c b/SDS/sds_rad.c index 45b3c3e4..debd6cfe 100644 --- a/SDS/sds_rad.c +++ b/SDS/sds_rad.c @@ -1,6 +1,6 @@ /* sds_rad.c: SDS 940 fixed head disk simulator - Copyright (c) 2001-2004, Robert M. Supnik + Copyright (c) 2001-2005, 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"), @@ -19,11 +19,11 @@ 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 + 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 + 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 @@ -36,32 +36,35 @@ /* 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 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))) -#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 } }; +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); @@ -73,50 +76,54 @@ t_stat rad (uint32 fnc, uint32 inst, uint32 *dat); /* RAD data structures - rad_dev device descriptor - rad_unit unit descriptor - rad_reg register list + 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) }; +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 } }; + { 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 } }; + { 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 }; - + "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 + + 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) @@ -125,93 +132,102 @@ int32 t, lun, new_ch; uint32 p; uint32 *fbuf = rad_unit.filebuf; -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; +switch (fnc) { /* case function */ -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_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_DISC: /* disconnect */ - rad_end_op (0); /* normal term */ - if (inst & DEV_OUT) return rad_fill (rad_sba); /* fill write */ - 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_WREOR: /* write eor */ - rad_end_op (CHF_EOR); /* eor term */ - return rad_fill (rad_sba); /* fill write */ + case IO_DISC: /* disconnect */ + rad_end_op (0); /* normal term */ + if (inst & DEV_OUT) return rad_fill (rad_sba); /* fill write */ + break; -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_WREOR: /* write eor */ + rad_end_op (CHF_EOR); /* eor term */ + return rad_fill (rad_sba); /* fill write */ -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; } - if (rad_sba & 1) *dat = fbuf[p] & 07777; /* odd byte? */ - else *dat = (fbuf[p] >> 12) & 07777; /* even */ - rad_sba = rad_adjda (rad_sba, 1); /* next byte */ - break; + 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_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; } - if (rad_sba & 1) fbuf[p] = fbuf[p] | (*dat & 07777); /* odd byte? */ - else fbuf[p] = (*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; + 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; + } + if (rad_sba & 1) *dat = fbuf[p] & 07777; /* odd byte? */ + else *dat = (fbuf[p] >> 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; + } + if (rad_sba & 1) fbuf[p] = fbuf[p] | (*dat & 07777); /* odd byte? */ + else fbuf[p] = (*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; + } -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 */ +*dat = GET_SECTOR (rad_time * RAD_NUMWD); /* ret curr sec */ return SCPE_OK; } @@ -219,7 +235,7 @@ return SCPE_OK; t_stat pot_rada (uint32 num, uint32 *dat) { -rad_da = (*dat) & RAD_AMASK; /* save dsk addr */ +rad_da = (*dat) & RAD_AMASK; /* save dsk addr */ return SCPE_OK; } @@ -227,8 +243,8 @@ return SCPE_OK; t_stat rad_svc (UNIT *uptr) { -xfr_req = xfr_req | XFR_RAD; /* set xfr req */ -sim_activate (&rad_unit, rad_time); /* activate */ +xfr_req = xfr_req | XFR_RAD; /* set xfr req */ +sim_activate (&rad_unit, rad_time); /* activate */ return SCPE_OK; } @@ -238,12 +254,13 @@ t_stat rad_fill (int32 sba) { uint32 p = rad_da * RAD_NUMWD; uint32 *fbuf = rad_unit.filebuf; -int32 wa = (sba + 1) >> 1; /* whole words */ +int32 wa = (sba + 1) >> 1; /* whole words */ -if (sba && (p < rad_unit.capac)) { /* fill needed? */ +if (sba && (p < rad_unit.capac)) { /* fill needed? */ for ( ; wa < RAD_NUMWD; wa++) fbuf[p + wa] = 0; if ((p + wa) >= rad_unit.hwmark) rad_unit.hwmark = p + wa + 1; - rad_adjda (sba, RAD_NUMWD - 1); } /* inc da */ + rad_adjda (sba, RAD_NUMWD - 1); /* inc da */ + } return SCPE_OK; } @@ -252,12 +269,13 @@ return SCPE_OK; 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 */ +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; } @@ -265,24 +283,25 @@ return sba; 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 */ +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 */ +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 */ +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 index d3a8ff36..29c6baf9 100644 --- a/SDS/sds_stddev.c +++ b/SDS/sds_stddev.c @@ -1,6 +1,6 @@ /* sds_stddev.c: SDS 940 standard devices - Copyright (c) 2001-2004, Robert M. Supnik + Copyright (c) 2001-2005, 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"), @@ -19,31 +19,32 @@ 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 + 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 + ptr paper tape reader + ptp paper tape punch + tti keyboard + tto teleprinter - 29-Dec-03 RMS Added console backpressure support - 25-Apr-03 RMS Revised for extended file support + 29-Dec-03 RMS Added console backpressure support + 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 + +#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 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 */ +DSPT std_tplt[] = { { 1, 0 }, { 0, 0 } }; /* template */ DEVICE ptr_dev, ptp_dev; t_stat ptr (uint32 fnc, uint32 inst, uint32 *dat); @@ -66,79 +67,87 @@ 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 + 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 }; + 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 } }; + { 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 } }; + { 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 }; + "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 + 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 }; + 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 } }; + { 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 } }; + { 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 }; - + "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 + 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 }; @@ -146,29 +155,32 @@ 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 } }; + { 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 } }; + { 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 }; + "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_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 }; @@ -176,33 +188,36 @@ 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 } }; + { 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 } }; + { 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 }; - + "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 + 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 @@ -213,62 +228,69 @@ 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; +switch (fnc) { /* case function */ -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_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_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_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_WREOR: /* write eor */ - 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 */ + } -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 */ +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_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; } @@ -276,10 +298,10 @@ return SCPE_OK; 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 */ +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; } @@ -287,11 +309,11 @@ return; t_stat ptr_reset (DEVICE *dptr) { -chan_disc (ptr_dib.chan); /* disconnect */ -ptr_sor = 0; /* clear state */ +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 */ +xfr_req = xfr_req & ~XFR_PTR; /* clr xfr flag */ +sim_cancel (&ptr_unit); /* deactivate unit */ return SCPE_OK; } @@ -301,24 +323,24 @@ 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 */ +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 + 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. @@ -328,36 +350,39 @@ 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; +switch (fnc) { /* case function */ -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_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_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_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_WREOR: /* write eor */ - 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 */ + } -case IO_EOM1: /* EOM mode 1*/ -case IO_READ: /* read */ - CRETINS; } /* error */ return SCPE_OK; } - + /* Unit service */ t_stat ptp_svc (UNIT *uptr) @@ -365,11 +390,13 @@ 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 */ +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; } @@ -377,15 +404,17 @@ return r; 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 */ +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_IOERR; + } +ptp_unit.pos = ptp_unit.pos + 1; /* inc position */ return SCPE_OK; } @@ -393,10 +422,10 @@ return SCPE_OK; 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 */ +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; } @@ -404,23 +433,23 @@ return; t_stat ptp_reset (DEVICE *dptr) { -chan_disc (ptp_dib.chan); /* disconnect */ -ptp_ldr = 0; /* clear state */ +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 */ +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 + 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. @@ -430,69 +459,73 @@ 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; +switch (fnc) { /* case function */ -case IO_DISC: /* disconnect */ - xfr_req = xfr_req & ~XFR_TTI; /* clr xfr flag */ - break; + 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_READ: /* read */ - xfr_req = xfr_req & ~XFR_TTI; /* clr xfr flag */ - *dat = tti_unit.buf; /* get buf data */ - break; + case IO_DISC: /* disconnect */ + xfr_req = xfr_req & ~XFR_TTI; /* clr xfr flag */ + break; -case IO_WREOR: /* write eor */ - 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 */ + } -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 */ +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 == '\r') sim_putchar ('\n'); /* lf after cr */ - xfr_req = xfr_req | XFR_TTI; } /* set xfr flag */ -else sim_putchar (007); /* ding! */ + tti_unit.buf = ascii_to_sds[temp]; /* internal rep */ + sim_putchar (temp); /* echo */ + if (temp == '\r') sim_putchar ('\n'); /* 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 */ +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 + 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. @@ -502,34 +535,37 @@ t_stat tto (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 != 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; +switch (fnc) { /* case function */ -case IO_DISC: /* disconnect */ - xfr_req = xfr_req & ~XFR_TTO; /* clr xfr flag */ - sim_cancel (&tto_unit); /* deactivate unit */ - break; + 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_WRITE: /* write */ - xfr_req = xfr_req & ~XFR_TTO; /* clr xfr flag */ - tto_unit.buf = (*dat) & 077; /* save data */ - 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_WREOR: /* write eor */ - break; + case IO_WRITE: /* write */ + xfr_req = xfr_req & ~XFR_TTO; /* clr xfr flag */ + tto_unit.buf = (*dat) & 077; /* save data */ + sim_activate (&tto_unit, tto_unit.wait); /* activate */ + break; + + case IO_WREOR: /* write eor */ + break; -case IO_EOM1: /* EOM mode 1*/ -case IO_READ: /* read */ - CRETINS; } /* error */ + case IO_EOM1: /* EOM mode 1*/ + case IO_READ: /* read */ + CRETINS; /* error */ + } + return SCPE_OK; } - + /* Unit service */ t_stat tto_svc (UNIT *uptr) @@ -537,18 +573,20 @@ t_stat tto_svc (UNIT *uptr) int32 asc; t_stat r; -if (uptr->buf == TT_CR) asc = '\r'; /* control chars? */ +if (uptr->buf == TT_CR) asc = '\r'; /* control chars? */ else if (uptr->buf == TT_BS) asc = '\b'; else if (uptr->buf == TT_TB) asc = '\t'; -else asc = sds_to_ascii[uptr->buf]; /* translate */ -if ((r = sim_putchar_s (asc)) != SCPE_OK) { /* output; error? */ - sim_activate (uptr, uptr->wait); /* retry */ - return ((r == SCPE_STALL)? SCPE_OK: r); } /* !stall? report */ -uptr->pos = uptr->pos + 1; /* inc position */ -chan_set_ordy (tto_dib.chan); /* tto rdy */ -if (asc == '\r') { /* CR? */ - sim_putchar ('\n'); /* add lf */ - uptr->pos = uptr->pos + 1; } /* inc position */ +else asc = sds_to_ascii[uptr->buf]; /* translate */ +if ((r = sim_putchar_s (asc)) != SCPE_OK) { /* output; error? */ + sim_activate (uptr, uptr->wait); /* retry */ + return ((r == SCPE_STALL)? SCPE_OK: r); /* !stall? report */ + } +uptr->pos = uptr->pos + 1; /* inc position */ +chan_set_ordy (tto_dib.chan); /* tto rdy */ +if (asc == '\r') { /* CR? */ + sim_putchar ('\n'); /* add lf */ + uptr->pos = uptr->pos + 1; /* inc position */ + } return SCPE_OK; } @@ -556,9 +594,9 @@ return SCPE_OK; 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 */ +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 index b522ece8..1ea3f0de 100644 --- a/SDS/sds_sys.c +++ b/SDS/sds_sys.c @@ -1,6 +1,6 @@ /* sds_sys.c: SDS 940 simulator interface - Copyright (c) 2001-2004, Robert M Supnik + Copyright (c) 2001-2005, 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"), @@ -19,8 +19,8 @@ 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 + 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. */ @@ -47,12 +47,12 @@ 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 + 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"; @@ -62,85 +62,89 @@ 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 }; + &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" }; - + "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 */ + '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 }; + -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 }; - + 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,... + (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 @@ -154,21 +158,25 @@ 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 */ +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; } + 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; } } + 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; @@ -190,10 +198,11 @@ for (i = wd = 0; i < 4; ) { if (c == 0) continue; *ldr = 0; wd = (wd << 6) | (c & 077); - i++; } + i++; + } return wd; } - + t_stat sim_load (FILE *fileref, char *cptr, char *fnam, int flag) { int32 i, wd, buf[8]; @@ -203,50 +212,53 @@ 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 */ +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 */ + 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 */ +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; } + 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) +#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 }; + 017700000, 017377677, 027737677 + }; static const char *opcode[] = { "POP", "EIR", "DIR", @@ -292,11 +304,12 @@ static const char *opcode[] = { "ALC", "DSC", "ASC", "TOP", "CAT", "CET", "CZT", "CIT", - "CLA", "CLB", "CAB", /* encode only */ + "CLA", "CLB", "CAB", /* encode only */ "CBA", "CBX", "CXB", "XPO", "CXA", "CAX", "CNA", "CLX", NULL, - NULL }; + NULL + }; static const int32 opc_val[] = { 010000000+I_PPO, 000220002+I_NPN, 000220004+I_NPN, @@ -346,121 +359,136 @@ static const int32 opc_val[] = { 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 }; + -1 + }; static const char *chname[] = { - "W", "Y", "C", "D", "E", "F", "G", "H", NULL }; - + "W", "Y", "C", "D", "E", "F", "G", "H", NULL + }; + /* Register change decode Inputs: - *of = output stream - inst = mask bits + *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; } } +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 + *of = output stream + addr = current PC + *val = pointer to values + *uptr = pointer to unit + sw = switches Outputs: - return = status code + return = status code */ t_stat fprint_sym (FILE *of, t_addr addr, t_value *val, - UNIT *uptr, int32 sw) + 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 */ +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 (sw & SWMASK ('A')) { /* ASCII? */ if (inst > 0377) return SCPE_ARG; fprintf (of, FMTASC (inst & 0177)); - return SCPE_OK; } -if (sw & SWMASK ('C')) { /* character? */ + 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; } + 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? */ +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 */ + 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 + *cptr = pointer to input string + *tag = pointer to tag Outputs: - cptr = updated pointer to input string + cptr = updated pointer to input string */ char *get_tag (char *cptr, t_value *tag) @@ -468,23 +496,23 @@ 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 */ +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 */ +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 + *cptr = pointer to input string + addr = current PC + uptr = pointer to unit + *val = pointer to output values + sw = switches Outputs: - status = error status + status = error status */ t_stat parse_sym (char *cptr, t_addr addr, UNIT *uptr, t_value *val, int32 sw) @@ -498,79 +526,93 @@ 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 */ + if (cptr[0] == 0) return SCPE_ARG; /* must have 1 char */ val[0] = (t_value) cptr[0] | 0200; - return SCPE_OK; } + return SCPE_OK; + } if ((sw & SWMASK ('C')) || ((*cptr == '"') && cptr++)) { /* string? */ - if (cptr[0] == 0) return SCPE_ARG; /* must have 1 char */ + 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 */ + 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; + } -cptr = get_glyph (cptr, gbuf, 0); /* get opcode */ +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 */ +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? */ +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/vax_cis.c b/VAX/vax_cis.c index c2a689cc..cda1eec0 100644 --- a/VAX/vax_cis.c +++ b/VAX/vax_cis.c @@ -1,6 +1,6 @@ /* vax_cis.c: VAX CIS instructions - Copyright (c) 2004, Robert M Supnik + Copyright (c) 2004-2005, 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"), @@ -19,14 +19,14 @@ 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 + 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. On a full VAX, this module simulates the VAX commercial instruction set (CIS). On a subset VAX, this module implements the emulated instruction fault. - 12-Apr-04 RMS Cloned from pdp11_cis.c and vax_cpu1.c + 12-Apr-04 RMS Cloned from pdp11_cis.c and vax_cpu1.c Zero length decimal strings require either zero bytes (trailing) or one byte (separate, packed). @@ -36,28 +36,27 @@ interruptible by faults, but decimal instructions run to completion. The code is unoptimized. */ - + #include "vax_defs.h" #if defined (FULL_VAX) /* Decimal string structure */ -#define DSTRLNT 4 -#define DSTRMAX (DSTRLNT - 1) -#define MAXDVAL 429496730 /* 2^32 / 10 */ +#define DSTRLNT 4 +#define DSTRMAX (DSTRLNT - 1) +#define MAXDVAL 429496730 /* 2^32 / 10 */ -#define C_SPACE 0x20 /* ASCII chars */ -#define C_PLUS 0x2B -#define C_MINUS 0x2D -#define C_ZERO 0x30 -#define C_NINE 0x39 +#define C_SPACE 0x20 /* ASCII chars */ +#define C_PLUS 0x2B +#define C_MINUS 0x2D +#define C_ZERO 0x30 +#define C_NINE 0x39 -struct dstr { - uint32 sign; - uint32 val[DSTRLNT]; }; - -typedef struct dstr DSTR; +typedef struct { + uint32 sign; + uint32 val[DSTRLNT]; + } DSTR; static DSTR Dstr_zero = { 0, 0, 0, 0, 0 }; static DSTR Dstr_one = { 0, 0x10, 0, 0, 0 }; @@ -93,7 +92,7 @@ int32 edit_read_sign (int32 acc); extern int32 Read (uint32 va, int32 lnt, int32 acc); extern void Write (uint32 va, int32 val, int32 lnt, int32 acc); extern int32 eval_int (void); - + /* CIS emulator */ int32 op_cis (int32 *op, int32 cc, int32 opc, int32 acc) @@ -106,850 +105,850 @@ t_stat r; DSTR accum, src1, src2, dst; DSTR mptable[10]; -switch (opc) { /* case on opcode */ - +switch (opc) { /* case on opcode */ + /* MOVTC Operands if PSL = 0: - op[0:1] = source string descriptor - op[2] = fill character - op[3] = table address - op[4:5] = destination string descriptor + op[0:1] = source string descriptor + op[2] = fill character + op[3] = table address + op[4:5] = destination string descriptor Registers if PSL = 1: - R[0] = delta-PC/fill/source string length - R[1] = source string address - R[2] = number of bytes remaining to move - R[3] = table address - R[4] = destination string length - R[5] = destination string address + R[0] = delta-PC/fill/source string length + R[1] = source string address + R[2] = number of bytes remaining to move + R[3] = table address + R[4] = destination string length + R[5] = destination string address Condition codes: - NZC = set from op[0]:op[4] - V = 0 + NZC = set from op[0]:op[4] + V = 0 Registers: - R0 = src length remaining, or 0 - R1 = addr of end of source string + 1 - R2 = 0 - R3 = table address - R4 = 0 - R5 = addr of end of dest string + 1 + R0 = src length remaining, or 0 + R1 = addr of end of source string + 1 + R2 = 0 + R3 = table address + R4 = 0 + R5 = addr of end of dest string + 1 */ -case MOVTC: - 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; /* remaining move */ - R[4] = R[4] & STR_LNMASK; - } - else { - R[0] = STR_PACK (op[2], op[0]); /* src len, fill */ - R[1] = op[1]; /* src addr */ - fill = op[2]; /* set fill */ - R[3] = op[3]; /* table addr */ - R[4] = op[4]; /* dst len */ - R[5] = op[5]; /* dst addr */ - CC_CMP_W (op[0], op[4]); /* set cc's */ - R[2] = (op[0] < op[4])? op[0]: op[4]; /* remaining move */ - PSL = PSL | PSL_FPD; /* set FPD */ - } - if (R[2]) { /* move to do? */ - int32 mvl; - mvl = R[0] & STR_LNMASK; /* orig move len */ - if (mvl >= R[4]) mvl = R[4]; - if (((uint32) R[1]) < ((uint32) R[5])) { /* backward? */ - while (R[2]) { /* loop thru char */ - t = Read ((R[1] + R[2] - 1) & LMASK, L_BYTE, RA); - c = Read ((R[3] + t) & LMASK, L_BYTE, RA); - Write ((R[5] + R[2] - 1) & LMASK, c, L_BYTE, WA); - R[2] = (R[2] - 1) & STR_LNMASK; - } - R[1] = (R[1] + mvl) & LMASK; /* adv src, dst */ - R[5] = (R[5] + mvl) & LMASK; - } - else { /* forward */ - while (R[2]) { /* loop thru char */ - t = Read (R[1], L_BYTE, RA); /* read src */ - c = Read ((R[3] + t) & LMASK, L_BYTE, RA); - Write (R[5], c, L_BYTE, WA); /* write dst */ - R[1] = (R[1] + 1) & LMASK; /* adv src, dst */ - R[2] = (R[2] - 1) & STR_LNMASK; - R[5] = (R[5] + 1) & LMASK; - } - } - R[0] = (R[0] & ~STR_LNMASK) | ((R[0] - mvl) & STR_LNMASK); - R[4] = (R[4] - mvl) & STR_LNMASK; /* update lengths */ - } - while (R[4]) { /* fill if needed */ - Write (R[5], fill, L_BYTE, WA); - R[4] = (R[4] - 1) & STR_LNMASK; - R[5] = (R[5] + 1) & LMASK; /* adv dst */ - } - R[0] = R[0] & STR_LNMASK; /* mask off state */ - PSL = PSL & ~PSL_FPD; /* all reg correct */ - return cc; - + case MOVTC: + 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; /* remaining move */ + R[4] = R[4] & STR_LNMASK; + } + else { + R[0] = STR_PACK (op[2], op[0]); /* src len, fill */ + R[1] = op[1]; /* src addr */ + fill = op[2]; /* set fill */ + R[3] = op[3]; /* table addr */ + R[4] = op[4]; /* dst len */ + R[5] = op[5]; /* dst addr */ + CC_CMP_W (op[0], op[4]); /* set cc's */ + R[2] = (op[0] < op[4])? op[0]: op[4]; /* remaining move */ + PSL = PSL | PSL_FPD; /* set FPD */ + } + if (R[2]) { /* move to do? */ + int32 mvl; + mvl = R[0] & STR_LNMASK; /* orig move len */ + if (mvl >= R[4]) mvl = R[4]; + if (((uint32) R[1]) < ((uint32) R[5])) { /* backward? */ + while (R[2]) { /* loop thru char */ + t = Read ((R[1] + R[2] - 1) & LMASK, L_BYTE, RA); + c = Read ((R[3] + t) & LMASK, L_BYTE, RA); + Write ((R[5] + R[2] - 1) & LMASK, c, L_BYTE, WA); + R[2] = (R[2] - 1) & STR_LNMASK; + } + R[1] = (R[1] + mvl) & LMASK; /* adv src, dst */ + R[5] = (R[5] + mvl) & LMASK; + } + else { /* forward */ + while (R[2]) { /* loop thru char */ + t = Read (R[1], L_BYTE, RA); /* read src */ + c = Read ((R[3] + t) & LMASK, L_BYTE, RA); + Write (R[5], c, L_BYTE, WA); /* write dst */ + R[1] = (R[1] + 1) & LMASK; /* adv src, dst */ + R[2] = (R[2] - 1) & STR_LNMASK; + R[5] = (R[5] + 1) & LMASK; + } + } + R[0] = (R[0] & ~STR_LNMASK) | ((R[0] - mvl) & STR_LNMASK); + R[4] = (R[4] - mvl) & STR_LNMASK; /* update lengths */ + } + while (R[4]) { /* fill if needed */ + Write (R[5], fill, L_BYTE, WA); + R[4] = (R[4] - 1) & STR_LNMASK; + R[5] = (R[5] + 1) & LMASK; /* adv dst */ + } + R[0] = R[0] & STR_LNMASK; /* mask off state */ + PSL = PSL & ~PSL_FPD; /* all reg correct */ + return cc; + /* MOVTUC Operands: - op[0:1] = source string descriptor - op[2] = escape character - op[3] = table address - op[4:5] = destination string descriptor + op[0:1] = source string descriptor + op[2] = escape character + op[3] = table address + op[4:5] = destination string descriptor Registers if PSL = 1: - R[0] = delta-PC/match/source string length - R[1] = source string address - R[2] = not used - R[3] = table address - R[4] = destination string length - R[5] = destination string address + R[0] = delta-PC/match/source string length + R[1] = source string address + R[2] = not used + R[3] = table address + R[4] = destination string length + R[5] = destination string address Condition codes: - NZC = set from op[0]:op[4] - V = 1 if match to escape character + NZC = set from op[0]:op[4] + V = 1 if match to escape character Registers: - R0 = src length remaining, or 0 - R1 = addr of end of source string + 1 - R2 = 0 - R3 = table address - R4 = dst length remaining, or 0 - R5 = addr of end of dest string + 1 + R0 = src length remaining, or 0 + R1 = addr of end of source string + 1 + R2 = 0 + R3 = table address + R4 = dst length remaining, or 0 + R5 = addr of end of dest string + 1 */ -case MOVTUC: - if (PSL & PSL_FPD) { /* FPD set? */ - SETPC (fault_PC + STR_GETDPC (R[0])); /* reset PC */ - fill = STR_GETCHR (R[0]); /* get match */ - R[4] = R[4] & STR_LNMASK; - } - else { - R[0] = STR_PACK (op[2], op[0]); /* src len, fill */ - R[1] = op[1]; /* src addr */ - fill = op[2]; /* set match */ - R[3] = op[3]; /* table addr */ - R[4] = op[4]; /* dst len */ - R[5] = op[5]; /* dst addr */ - CC_CMP_W (op[0], op[4]); /* set cc's */ - PSL = PSL | PSL_FPD; /* set FPD */ - } - while ((R[0] & STR_LNMASK) && R[4]) { /* while src & dst */ - t = Read (R[1], L_BYTE, RA); /* read src */ - if (t == fill) { /* stop char? */ - cc = cc | CC_V; /* set V, done */ - break; - } - c = Read ((R[3] + t) & LMASK, L_BYTE, RA); /* translate */ - Write (R[5], c, L_BYTE, WA); /* write dst */ - R[0] = (R[0] & ~STR_LNMASK) | ((R[0] - 1) & STR_LNMASK); - R[1] = (R[1] + 1) & LMASK; - R[4] = (R[4] - 1) & STR_LNMASK; /* adv src, dst */ - R[5] = (R[5] + 1) & LMASK; - } - R[0] = R[0] & STR_LNMASK; /* mask off state */ - R[2] = 0; - PSL = PSL & ~PSL_FPD; - return cc; - + case MOVTUC: + if (PSL & PSL_FPD) { /* FPD set? */ + SETPC (fault_PC + STR_GETDPC (R[0])); /* reset PC */ + fill = STR_GETCHR (R[0]); /* get match */ + R[4] = R[4] & STR_LNMASK; + } + else { + R[0] = STR_PACK (op[2], op[0]); /* src len, fill */ + R[1] = op[1]; /* src addr */ + fill = op[2]; /* set match */ + R[3] = op[3]; /* table addr */ + R[4] = op[4]; /* dst len */ + R[5] = op[5]; /* dst addr */ + CC_CMP_W (op[0], op[4]); /* set cc's */ + PSL = PSL | PSL_FPD; /* set FPD */ + } + while ((R[0] & STR_LNMASK) && R[4]) { /* while src & dst */ + t = Read (R[1], L_BYTE, RA); /* read src */ + if (t == fill) { /* stop char? */ + cc = cc | CC_V; /* set V, done */ + break; + } + c = Read ((R[3] + t) & LMASK, L_BYTE, RA); /* translate */ + Write (R[5], c, L_BYTE, WA); /* write dst */ + R[0] = (R[0] & ~STR_LNMASK) | ((R[0] - 1) & STR_LNMASK); + R[1] = (R[1] + 1) & LMASK; + R[4] = (R[4] - 1) & STR_LNMASK; /* adv src, dst */ + R[5] = (R[5] + 1) & LMASK; + } + R[0] = R[0] & STR_LNMASK; /* mask off state */ + R[2] = 0; + PSL = PSL & ~PSL_FPD; + return cc; + /* MATCHC Operands: - op[0:1] = substring descriptor - op[2:3] = string descriptor + op[0:1] = substring descriptor + op[2:3] = string descriptor Registers if PSL = 1: - R[0] = delta-PC/match/substring length - R[1] = substring address - R[2] = source string length - R[3] = source string address + R[0] = delta-PC/match/substring length + R[1] = substring address + R[2] = source string length + R[3] = source string address Condition codes: - NZ = set from R0 - VC = 0 + NZ = set from R0 + VC = 0 Registers: - R0 = if match, 0, else, op[0] - R1 = if match, op[0] + op[1], else, op[1] - R2 = if match, src bytes remaining, else, 0 - R3 = if match, end of substr, else, op[2] + op[3] + R0 = if match, 0, else, op[0] + R1 = if match, op[0] + op[1], else, op[1] + R2 = if match, src bytes remaining, else, 0 + R3 = if match, end of substr, else, op[2] + op[3] 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) - - This instruction can potentially run a very long time - worst - case execution on a real VAX-11/780 was more than 30 minutes. - Accordingly, the instruction tests for interrupts and stops - if one is found. + - 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) + - This instruction can potentially run a very long time - worst + case execution on a real VAX-11/780 was more than 30 minutes. + Accordingly, the instruction tests for interrupts and stops + if one is found. */ -case MATCHC: - if (PSL & PSL_FPD) { /* FPD? */ - SETPC (fault_PC + STR_GETDPC (R[0])); /* reset PC */ - R[2] = R[2] & STR_LNMASK; - } - else { - R[0] = STR_PACK (0, op[0]); /* srclen + FPD data */ - R[1] = op[1]; /* save operands */ - R[2] = op[2]; - R[3] = op[3]; - PSL = PSL | PSL_FPD; /* set FPD */ - } - for (match = 0; R[2] >= (R[0] & STR_LNMASK); ) { - for (i = 0, match = 1; match && (i < (R[0] & STR_LNMASK)); i++) { - c = Read ((R[1] + i) & LMASK, L_BYTE, RA); - t = Read ((R[3] + i) & LMASK, L_BYTE, RA); - match = (c == t); /* continue if match */ - } /* end for substring */ - if (match) break; /* exit if match */ - R[2] = (R[2] - 1) & STR_LNMASK; /* decr src length */ - R[3] = (R[3] + 1) & LMASK; /* next string char */ - if (i >= sim_interval) { /* done with interval? */ - sim_interval = 0; - if (r = sim_process_event ()) { /* presumably WRU */ - PC = fault_PC; /* backup up PC */ - ABORT (r); /* abort flushes IB */ - } - SET_IRQL; /* update interrupts */ - if (trpirq) ABORT (ABORT_INTR); /* pending? stop */ - } - else sim_interval = sim_interval - i; - } /* end for string */ - R[0] = R[0] & STR_LNMASK; - if (match) { /* if match */ - R[1] = (R[1] + R[0]) & LMASK; - R[2] = (R[2] - R[0]) & STR_LNMASK; - R[3] = (R[3] + R[0]) & LMASK; - R[0] = 0; - } - else { /* if no match */ - R[3] = (R[3] + R[2]) & LMASK; - R[2] = 0; - } - PSL = PSL & ~PSL_FPD; - CC_IIZZ_L (R[0]); /* set cc's */ - return cc; - + case MATCHC: + if (PSL & PSL_FPD) { /* FPD? */ + SETPC (fault_PC + STR_GETDPC (R[0])); /* reset PC */ + R[2] = R[2] & STR_LNMASK; + } + else { + R[0] = STR_PACK (0, op[0]); /* srclen + FPD data */ + R[1] = op[1]; /* save operands */ + R[2] = op[2]; + R[3] = op[3]; + PSL = PSL | PSL_FPD; /* set FPD */ + } + for (match = 0; R[2] >= (R[0] & STR_LNMASK); ) { + for (i = 0, match = 1; match && (i < (R[0] & STR_LNMASK)); i++) { + c = Read ((R[1] + i) & LMASK, L_BYTE, RA); + t = Read ((R[3] + i) & LMASK, L_BYTE, RA); + match = (c == t); /* continue if match */ + } /* end for substring */ + if (match) break; /* exit if match */ + R[2] = (R[2] - 1) & STR_LNMASK; /* decr src length */ + R[3] = (R[3] + 1) & LMASK; /* next string char */ + if (i >= sim_interval) { /* done with interval? */ + sim_interval = 0; + if (r = sim_process_event ()) { /* presumably WRU */ + PC = fault_PC; /* backup up PC */ + ABORT (r); /* abort flushes IB */ + } + SET_IRQL; /* update interrupts */ + if (trpirq) ABORT (ABORT_INTR); /* pending? stop */ + } + else sim_interval = sim_interval - i; + } /* end for string */ + R[0] = R[0] & STR_LNMASK; + if (match) { /* if match */ + R[1] = (R[1] + R[0]) & LMASK; + R[2] = (R[2] - R[0]) & STR_LNMASK; + R[3] = (R[3] + R[0]) & LMASK; + R[0] = 0; + } + else { /* if no match */ + R[3] = (R[3] + R[2]) & LMASK; + R[2] = 0; + } + PSL = PSL & ~PSL_FPD; + CC_IIZZ_L (R[0]); /* set cc's */ + return cc; + /* CRC Operands: - op[0] = table address - op[1] = initial CRC - op[2:3] = source string descriptor + op[0] = table address + op[1] = initial CRC + op[2:3] = source string descriptor Registers if PSL = 1: - R[0] = result - R[1] = table address - R[2] = delta-PC/0/source string length - R[3] = source string address + R[0] = result + R[1] = table address + R[2] = delta-PC/0/source string length + R[3] = source string address Condition codes: - NZ = set from result - VC = 0 + NZ = set from result + VC = 0 Registers: - R0 = result - R1 = 0 - R2 = 0 - R3 = addr + 1 of last byte in source string + R0 = result + R1 = 0 + R2 = 0 + R3 = addr + 1 of last byte in source string */ -case CRC: - if (PSL & PSL_FPD) { /* FPD? */ - SETPC (fault_PC + STR_GETDPC (R[2])); /* reset PC */ - } - else { - R[2] = STR_PACK (0, op[2]); /* srclen + FPD data */ - R[0] = op[1]; /* save operands */ - R[1] = op[0]; - R[3] = op[3]; - PSL = PSL | PSL_FPD; /* set FPD */ - } - while ((R[2] & STR_LNMASK) != 0) { /* loop thru chars */ - c = Read (R[3], L_BYTE, RA); /* get char */ - t = R[0] ^ c; /* XOR to CRC */ - t = do_crc_4b (t, R[1], acc); /* do 4b shift */ - R[0] = do_crc_4b (t, R[1], acc); /* do 4b shift */ - R[3] = (R[3] + 1) & LMASK; - R[2] = R[2] - 1; - } - R[1] = 0; - R[2] = 0; - PSL = PSL & ~PSL_FPD; - CC_IIZZ_L (R[0]); /* set cc's */ - return cc; - + case CRC: + if (PSL & PSL_FPD) { /* FPD? */ + SETPC (fault_PC + STR_GETDPC (R[2])); /* reset PC */ + } + else { + R[2] = STR_PACK (0, op[2]); /* srclen + FPD data */ + R[0] = op[1]; /* save operands */ + R[1] = op[0]; + R[3] = op[3]; + PSL = PSL | PSL_FPD; /* set FPD */ + } + while ((R[2] & STR_LNMASK) != 0) { /* loop thru chars */ + c = Read (R[3], L_BYTE, RA); /* get char */ + t = R[0] ^ c; /* XOR to CRC */ + t = do_crc_4b (t, R[1], acc); /* do 4b shift */ + R[0] = do_crc_4b (t, R[1], acc); /* do 4b shift */ + R[3] = (R[3] + 1) & LMASK; + R[2] = R[2] - 1; + } + R[1] = 0; + R[2] = 0; + PSL = PSL & ~PSL_FPD; + CC_IIZZ_L (R[0]); /* set cc's */ + return cc; + /* MOVP Operands: - op[0] = length - op[1] = source string address - op[2] = dest string address + op[0] = length + op[1] = source string address + op[2] = dest string address Condition codes: - NZ = set from result - V = 0 - C = unchanged + NZ = set from result + V = 0 + C = unchanged Registers: - R0 = 0 - R1 = addr of source string - R2 = 0 - R3 = addr of dest string + R0 = 0 + R1 = addr of source string + R2 = 0 + R3 = addr of dest string */ -case MOVP: - if ((PSL & PSL_FPD) || (op[0] > 31)) - RSVD_OPND_FAULT; - ReadDstr (op[0], op[1], &dst, acc); /* read source */ - cc = WriteDstr (op[0], op[2], &dst, 0, acc) | /* write dest */ - (cc & CC_C); /* preserve C */ - R[0] = 0; - R[1] = op[1]; - R[2] = 0; - R[3] = op[2]; - return cc; - + case MOVP: + if ((PSL & PSL_FPD) || (op[0] > 31)) + RSVD_OPND_FAULT; + ReadDstr (op[0], op[1], &dst, acc); /* read source */ + cc = WriteDstr (op[0], op[2], &dst, 0, acc) | /* write dest */ + (cc & CC_C); /* preserve C */ + R[0] = 0; + R[1] = op[1]; + R[2] = 0; + R[3] = op[2]; + return cc; + /* ADDP4, ADDP6, SUBP4, SUBP6 Operands: - op[0:1] = src1 string descriptor - op[2:3] = src2 string descriptor - (ADDP6, SUBP6 only) - op[4:5] = dest string descriptor + op[0:1] = src1 string descriptor + op[2:3] = src2 string descriptor + (ADDP6, SUBP6 only) + op[4:5] = dest string descriptor Condition codes: - NZV = set from result - C = 0 + NZV = set from result + C = 0 Registers: - R0 = 0 - R1 = addr of src1 string - R2 = 0 - R3 = addr of src2 string - (ADDP6, SUBP6 only) - R4 = 0 - R5 = addr of dest string + R0 = 0 + R1 = addr of src1 string + R2 = 0 + R3 = addr of src2 string + (ADDP6, SUBP6 only) + R4 = 0 + R5 = addr of dest string */ -case ADDP4: case SUBP4: - op[4] = op[2]; /* copy dst */ - op[5] = op[3]; -case ADDP6: case SUBP6: - if ((PSL & PSL_FPD) || (op[0] > 31) || - (op[2] > 31) || (op[4] > 31)) - RSVD_OPND_FAULT; - ReadDstr (op[0], op[1], &src1, acc); /* get src1 */ - ReadDstr (op[2], op[3], &src2, acc); /* get src2 */ - if (opc & 2) 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 */ - } - cc = WriteDstr (op[4], op[5], &dst, V, acc); /* store result */ - R[0] = 0; - R[1] = op[1]; - R[2] = 0; - R[3] = op[3]; - if (opc & 1) { /* ADDP6, SUBP6? */ - R[4] = 0; - R[5] = op[5]; - } - return cc; - + case ADDP4: case SUBP4: + op[4] = op[2]; /* copy dst */ + op[5] = op[3]; + case ADDP6: case SUBP6: + if ((PSL & PSL_FPD) || (op[0] > 31) || + (op[2] > 31) || (op[4] > 31)) + RSVD_OPND_FAULT; + ReadDstr (op[0], op[1], &src1, acc); /* get src1 */ + ReadDstr (op[2], op[3], &src2, acc); /* get src2 */ + if (opc & 2) 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 */ + } + cc = WriteDstr (op[4], op[5], &dst, V, acc); /* store result */ + R[0] = 0; + R[1] = op[1]; + R[2] = 0; + R[3] = op[3]; + if (opc & 1) { /* ADDP6, SUBP6? */ + R[4] = 0; + R[5] = op[5]; + } + return cc; + /* MULP Operands: - op[0:1] = src1 string descriptor - op[2:3] = src2 string descriptor - op[4:5] = dest string descriptor + op[0:1] = src1 string descriptor + op[2:3] = src2 string descriptor + op[4:5] = dest string descriptor Condition codes: - NZV = set from result - C = 0 + NZV = set from result + C = 0 Registers: - R0 = 0 - R1 = addr of src1 string - R2 = 0 - R3 = addr of src2 string - R4 = 0 - R5 = addr of dest string + R0 = 0 + R1 = addr of src1 string + R2 = 0 + R3 = addr of src2 string + R4 = 0 + R5 = addr of dest string */ -case MULP: - if ((PSL & PSL_FPD) || (op[0] > 31) || - (op[2] > 31) || (op[4] > 31)) - RSVD_OPND_FAULT; - dst = Dstr_zero; /* clear result */ - if (ReadDstr (op[0], op[1], &src1, acc) && /* read src1, src2 */ - ReadDstr (op[2], op[3], &src2, acc)) { /* if both > 0 */ - dst.sign = src1.sign ^ src2.sign; /* sign of result */ - accum = Dstr_zero; /* clear accum */ - NibbleRshift (&src1, 1, 0); /* shift out sign */ - CreateTable (&src1, mptable); /* create *1, *2, ... */ - for (i = 1; i < (DSTRLNT * 8); i++) { /* 31 iterations */ - d = (src2.val[i / 8] >> ((i % 8) * 4)) & 0xF; - if (d > 0) /* add in digit*mpcnd */ - AddDstr (&mptable[d], &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 */ - cc = WriteDstr (op[4], op[5], &dst, V, acc); /* store result */ - R[0] = 0; - R[1] = op[1]; - R[2] = 0; - R[3] = op[3]; - R[4] = 0; - R[5] = op[5]; - return cc; - + case MULP: + if ((PSL & PSL_FPD) || (op[0] > 31) || + (op[2] > 31) || (op[4] > 31)) + RSVD_OPND_FAULT; + dst = Dstr_zero; /* clear result */ + if (ReadDstr (op[0], op[1], &src1, acc) && /* read src1, src2 */ + ReadDstr (op[2], op[3], &src2, acc)) { /* if both > 0 */ + dst.sign = src1.sign ^ src2.sign; /* sign of result */ + accum = Dstr_zero; /* clear accum */ + NibbleRshift (&src1, 1, 0); /* shift out sign */ + CreateTable (&src1, mptable); /* create *1, *2, ... */ + for (i = 1; i < (DSTRLNT * 8); i++) { /* 31 iterations */ + d = (src2.val[i / 8] >> ((i % 8) * 4)) & 0xF; + if (d > 0) /* add in digit*mpcnd */ + AddDstr (&mptable[d], &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 */ + cc = WriteDstr (op[4], op[5], &dst, V, acc); /* store result */ + R[0] = 0; + R[1] = op[1]; + R[2] = 0; + R[3] = op[3]; + R[4] = 0; + R[5] = op[5]; + return cc; + /* DIVP Operands: - op[0:1] = src1 string descriptor - op[2:3] = src2 string descriptor - op[4:5] = dest string descriptor + op[0:1] = src1 string descriptor + op[2:3] = src2 string descriptor + op[4:5] = dest string descriptor Condition codes: - NZV = set from result - C = 0 + NZV = set from result + C = 0 Registers: - R0 = 0 - R1 = addr of src1 string - R2 = 0 - R3 = addr of src2 string - R4 = 0 - R5 = addr of dest string + R0 = 0 + R1 = addr of src1 string + R2 = 0 + R3 = addr of src2 string + R4 = 0 + R5 = addr of dest string */ -case DIVP: - if ((PSL & PSL_FPD) || (op[0] > 31) || - (op[2] > 31) || (op[4] > 31)) - RSVD_OPND_FAULT; - ldivr = ReadDstr (op[0], op[1], &src1, acc); /* get divisor */ - if (ldivr == 0) { /* divisor = 0? */ - SET_TRAP (TRAP_FLTDIV); /* dec div trap */ - return cc; - } - ldivr = LntDstr (&src1, ldivr); /* get exact length */ - ldivd = ReadDstr (op[2], op[3], &src2, acc); /* get dividend */ - ldivd = LntDstr (&src2, ldivd); /* get exact length */ - dst = Dstr_zero; /* clear dest */ - NibbleRshift (&src1, 1, 0); /* right justify ops */ - NibbleRshift (&src2, 1, 0); - if ((t = ldivd - ldivr) >= 0) { /* any divide to do? */ - dst.sign = src1.sign ^ src2.sign; /* calculate sign */ - 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 (d = 9; d > 0; d--) { /* find digit */ - if (CmpDstr (&src2, &mptable[d]) >= 0) { - SubDstr (&mptable[d], &src2, &src2); - dst.val[0] = dst.val[0] | d; - break; - } /* end if */ - } /* end for */ - NibbleLshift (&src2, 1, 0); /* shift dividend */ - NibbleLshift (&dst, 1, 0); /* shift quotient */ - } /* end divide loop */ - } /* end if */ - cc = WriteDstr (op[4], op[5], &dst, 0, acc); /* store result */ - R[0] = 0; - R[1] = op[1]; - R[2] = 0; - R[3] = op[3]; - R[4] = 0; - R[5] = op[5]; - return cc; - + case DIVP: + if ((PSL & PSL_FPD) || (op[0] > 31) || + (op[2] > 31) || (op[4] > 31)) + RSVD_OPND_FAULT; + ldivr = ReadDstr (op[0], op[1], &src1, acc); /* get divisor */ + if (ldivr == 0) { /* divisor = 0? */ + SET_TRAP (TRAP_FLTDIV); /* dec div trap */ + return cc; + } + ldivr = LntDstr (&src1, ldivr); /* get exact length */ + ldivd = ReadDstr (op[2], op[3], &src2, acc); /* get dividend */ + ldivd = LntDstr (&src2, ldivd); /* get exact length */ + dst = Dstr_zero; /* clear dest */ + NibbleRshift (&src1, 1, 0); /* right justify ops */ + NibbleRshift (&src2, 1, 0); + if ((t = ldivd - ldivr) >= 0) { /* any divide to do? */ + dst.sign = src1.sign ^ src2.sign; /* calculate sign */ + 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 (d = 9; d > 0; d--) { /* find digit */ + if (CmpDstr (&src2, &mptable[d]) >= 0) { + SubDstr (&mptable[d], &src2, &src2); + dst.val[0] = dst.val[0] | d; + break; + } /* end if */ + } /* end for */ + NibbleLshift (&src2, 1, 0); /* shift dividend */ + NibbleLshift (&dst, 1, 0); /* shift quotient */ + } /* end divide loop */ + } /* end if */ + cc = WriteDstr (op[4], op[5], &dst, 0, acc); /* store result */ + R[0] = 0; + R[1] = op[1]; + R[2] = 0; + R[3] = op[3]; + R[4] = 0; + R[5] = op[5]; + return cc; + /* CMPP3, CMPP4 Operands (CMPP3): - op[0] = string length - op[1], op[2] = string lengths + op[0] = string length + op[1], op[2] = string lengths Operands (CMPP4): - op[0:1] = string1 descriptor - op[2:3] = string2 descriptor + op[0:1] = string1 descriptor + op[2:3] = string2 descriptor Condition codes: - NZ = set from comparison - VC = 0 + NZ = set from comparison + VC = 0 Registers: - R0 = 0 - R1 = addr of src1 string - R2 = 0 - R3 = addr of src2 string + R0 = 0 + R1 = addr of src1 string + R2 = 0 + R3 = addr of src2 string */ -case CMPP3: - op[3] = op[2]; /* reposition ops */ - op[2] = op[0]; -case CMPP4: - if ((PSL & PSL_FPD) || (op[0] > 31) || (op[2] > 31)) - RSVD_OPND_FAULT; - ReadDstr (op[0], op[1], &src1, acc); /* get src1 */ - ReadDstr (op[1], op[2], &src2, acc); /* get src2 */ - cc = 0; - if (src1.sign != src2.sign) cc = (src1.sign)? CC_N: 0; - else { - t = CmpDstr (&src1, &src2); /* compare strings */ - if (t < 0) cc = (src1.sign? 0: CC_N); - else if (t > 0) cc = (src1.sign? CC_N: 0); - else cc = CC_Z; - } - R[0] = 0; - R[1] = op[1]; - R[2] = 0; - R[3] = op[3]; - return cc ; - + case CMPP3: + op[3] = op[2]; /* reposition ops */ + op[2] = op[0]; + case CMPP4: + if ((PSL & PSL_FPD) || (op[0] > 31) || (op[2] > 31)) + RSVD_OPND_FAULT; + ReadDstr (op[0], op[1], &src1, acc); /* get src1 */ + ReadDstr (op[1], op[2], &src2, acc); /* get src2 */ + cc = 0; + if (src1.sign != src2.sign) cc = (src1.sign)? CC_N: 0; + else { + t = CmpDstr (&src1, &src2); /* compare strings */ + if (t < 0) cc = (src1.sign? 0: CC_N); + else if (t > 0) cc = (src1.sign? CC_N: 0); + else cc = CC_Z; + } + R[0] = 0; + R[1] = op[1]; + R[2] = 0; + R[3] = op[3]; + return cc ; + /* ASHP Operands: - op[0] = shift count - op[1:2] = source string descriptor - op[3] = round digit - op[4:5] = dest string descriptor + op[0] = shift count + op[1:2] = source string descriptor + op[3] = round digit + op[4:5] = dest string descriptor Condition codes: - NZV = set from result - C = 0 + NZV = set from result + C = 0 Registers: - R0 = 0 - R1 = addr of src1 string - R2 = 0 - R3 = addr of src2 string + R0 = 0 + R1 = addr of src1 string + R2 = 0 + R3 = addr of src2 string */ -case ASHP: - if ((PSL & PSL_FPD) || (op[1] > 31) || (op[4] > 31)) - RSVD_OPND_FAULT; - ReadDstr (op[1], op[2], &src1, acc); /* get source */ - V = 0; /* init V */ - shift = op[0]; /* get shift count */ - if (shift & BSIGN) { /* right shift? */ - shift = BMASK + 1 - shift; /* !shift! */ - WordRshift (&src1, shift / 8); /* do word shifts */ - NibbleRshift (&src1, shift % 8, 0); /* do nibble shifts */ - t = op[3] & 0xF; /* get round nibble */ - if ((t + (src1.val[0] & 0xF)) > 9) /* rounding needed? */ - AddDstr (&src1, &Dstr_one, &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 */ - cc = WriteDstr (op[4], op[5], &src1, V, acc); /* store result */ - R[0] = 0; - R[1] = op[2]; - R[2] = 0; - R[3] = op[5]; - return cc ; - + case ASHP: + if ((PSL & PSL_FPD) || (op[1] > 31) || (op[4] > 31)) + RSVD_OPND_FAULT; + ReadDstr (op[1], op[2], &src1, acc); /* get source */ + V = 0; /* init V */ + shift = op[0]; /* get shift count */ + if (shift & BSIGN) { /* right shift? */ + shift = BMASK + 1 - shift; /* !shift! */ + WordRshift (&src1, shift / 8); /* do word shifts */ + NibbleRshift (&src1, shift % 8, 0); /* do nibble shifts */ + t = op[3] & 0xF; /* get round nibble */ + if ((t + (src1.val[0] & 0xF)) > 9) /* rounding needed? */ + AddDstr (&src1, &Dstr_one, &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 */ + cc = WriteDstr (op[4], op[5], &src1, V, acc); /* store result */ + R[0] = 0; + R[1] = op[2]; + R[2] = 0; + R[3] = op[5]; + return cc ; + /* CVTPL Operands: - op[0:1] = source string descriptor - op[2] = memory flag/register number - op[3] = memory address + op[0:1] = source string descriptor + op[2] = memory flag/register number + op[3] = memory address Condition codes: - NZV = set from result - C = 0 + NZV = set from result + C = 0 Registers: - R0 = 0 - R1 = addr of source string - R2 = 0 - R3 = 0 + R0 = 0 + R1 = addr of source string + R2 = 0 + R3 = 0 */ -case CVTPL: - if ((PSL & PSL_FPD) || (op[0] > 31)) - RSVD_OPND_FAULT; - ReadDstr (op[0], op[1], &src1, acc); /* get source */ - V = result = 0; /* clear V, result */ - for (i = (DSTRLNT * 8) - 1; i > 0; i--) { /* loop thru digits */ - d = (src1.val[i / 8] >> ((i % 8) * 4)) & 0xF; - if (d || result || V) { /* skip initial 0's */ - if (result >= MAXDVAL) V = 1; - result = ((result * 10) + d) & LMASK; - if (result < d) V = 1; - } /* end if */ - } /* end for */ - if (src1.sign) result = (~result + 1) & LMASK; /* negative? */ - if (src1.sign ^ ((result & LSIGN) != 0)) V = 1; /* test for overflow */ - if (op[2] >= 0) R[op[2]] = result; - else Write (op[3], result, L_LONG, WA); - if (V) SET_TRAP (TRAP_INTOV); - R[0] = 0; - R[1] = op[1]; - R[2] = 0; - R[3] = 0; - CC_IIZZ_L (result); - return cc | V; - + case CVTPL: + if ((PSL & PSL_FPD) || (op[0] > 31)) + RSVD_OPND_FAULT; + ReadDstr (op[0], op[1], &src1, acc); /* get source */ + V = result = 0; /* clear V, result */ + for (i = (DSTRLNT * 8) - 1; i > 0; i--) { /* loop thru digits */ + d = (src1.val[i / 8] >> ((i % 8) * 4)) & 0xF; + if (d || result || V) { /* skip initial 0's */ + if (result >= MAXDVAL) V = 1; + result = ((result * 10) + d) & LMASK; + if (result < d) V = 1; + } /* end if */ + } /* end for */ + if (src1.sign) result = (~result + 1) & LMASK; /* negative? */ + if (src1.sign ^ ((result & LSIGN) != 0)) V = 1; /* test for overflow */ + if (op[2] >= 0) R[op[2]] = result; + else Write (op[3], result, L_LONG, WA); + if (V) SET_TRAP (TRAP_INTOV); + R[0] = 0; + R[1] = op[1]; + R[2] = 0; + R[3] = 0; + CC_IIZZ_L (result); + return cc | V; + /* CVTLP Operands: - op[0] = source long - op[1:2] = dest string descriptor + op[0] = source long + op[1:2] = dest string descriptor Condition codes: - NZV = set from result - C = 0 + NZV = set from result + C = 0 Registers: - R0 = 0 - R1 = 0 - R2 = 0 - R3 = addr of dest string + R0 = 0 + R1 = 0 + R2 = 0 + R3 = addr of dest string */ -case CVTLP: - if ((PSL & PSL_FPD) || (op[1] > 31)) - RSVD_OPND_FAULT; - dst = Dstr_zero; /* clear result */ - result = op[0]; - if ((result & LSIGN) != 0) { - dst.sign = 1; - result = (~result + 1) & LMASK; - } - for (i = 1; (i < (DSTRLNT * 8)) && result; i++) { - d = result % 10; - result = result / 10; - dst.val[i / 8] = dst.val[i / 8] | (d << ((i % 8) * 4)); - } - cc = WriteDstr (op[1], op[2], &dst, 0, acc); /* write result */ - R[0] = 0; - R[1] = 0; - R[2] = 0; - R[3] = op[2]; - return cc; - + case CVTLP: + if ((PSL & PSL_FPD) || (op[1] > 31)) + RSVD_OPND_FAULT; + dst = Dstr_zero; /* clear result */ + result = op[0]; + if ((result & LSIGN) != 0) { + dst.sign = 1; + result = (~result + 1) & LMASK; + } + for (i = 1; (i < (DSTRLNT * 8)) && result; i++) { + d = result % 10; + result = result / 10; + dst.val[i / 8] = dst.val[i / 8] | (d << ((i % 8) * 4)); + } + cc = WriteDstr (op[1], op[2], &dst, 0, acc); /* write result */ + R[0] = 0; + R[1] = 0; + R[2] = 0; + R[3] = op[2]; + return cc; + /* CVTSP Operands: - op[0:1] = source string descriptor - op[2:3] = dest string descriptor + op[0:1] = source string descriptor + op[2:3] = dest string descriptor Condition codes: - NZV = set from result - C = 0 + NZV = set from result + C = 0 Registers: - R0 = 0 - R1 = address of sign byte of source string - R2 = 0 - R3 = addr of dest string + R0 = 0 + R1 = address of sign byte of source string + R2 = 0 + R3 = addr of dest string */ -case CVTSP: - if ((PSL & PSL_FPD) || (op[0] > 31) || (op[2] > 31)) - RSVD_OPND_FAULT; - dst = Dstr_zero; /* clear result */ - t = Read (op[1], L_BYTE, RA); /* read source sign */ - if (t == C_MINUS) dst.sign = 1; /* sign -, */ - else if ((t != C_PLUS) && (t != C_SPACE)) /* + or blank? */ - RSVD_OPND_FAULT; - for (i = 1; i <= op[0]; i++) { /* loop thru chars */ - c = Read ((op[1] + op[0] + 1 - i) & LMASK, L_BYTE, RA); - if ((c < C_ZERO) || (c > C_NINE)) /* [0:9]? */ - RSVD_OPND_FAULT; - d = c & 0xF; - dst.val[i / 8] = dst.val[i / 8] | (d << ((i % 8) * 4)); - } - TestDstr (&dst); /* correct -0 */ - cc = WriteDstr (op[2], op[3], &dst, 0, acc); /* write result */ - R[0] = 0; - R[1] = op[1]; - R[2] = 0; - R[3] = op[3]; - return cc; - + case CVTSP: + if ((PSL & PSL_FPD) || (op[0] > 31) || (op[2] > 31)) + RSVD_OPND_FAULT; + dst = Dstr_zero; /* clear result */ + t = Read (op[1], L_BYTE, RA); /* read source sign */ + if (t == C_MINUS) dst.sign = 1; /* sign -, */ + else if ((t != C_PLUS) && (t != C_SPACE)) /* + or blank? */ + RSVD_OPND_FAULT; + for (i = 1; i <= op[0]; i++) { /* loop thru chars */ + c = Read ((op[1] + op[0] + 1 - i) & LMASK, L_BYTE, RA); + if ((c < C_ZERO) || (c > C_NINE)) /* [0:9]? */ + RSVD_OPND_FAULT; + d = c & 0xF; + dst.val[i / 8] = dst.val[i / 8] | (d << ((i % 8) * 4)); + } + TestDstr (&dst); /* correct -0 */ + cc = WriteDstr (op[2], op[3], &dst, 0, acc); /* write result */ + R[0] = 0; + R[1] = op[1]; + R[2] = 0; + R[3] = op[3]; + return cc; + /* CVTPS Operands: - op[0:1] = source string descriptor - op[2:3] = dest string descriptor + op[0:1] = source string descriptor + op[2:3] = dest string descriptor Condition codes: - NZV = set from result - C = 0 + NZV = set from result + C = 0 Registers: - R0 = 0 - R1 = addr of source string - R2 = 0 - R3 = addr of dest string + R0 = 0 + R1 = addr of source string + R2 = 0 + R3 = addr of dest string */ -case CVTPS: - if ((PSL & PSL_FPD) || (op[0] > 31) || (op[2] > 31)) - RSVD_OPND_FAULT; - ReadDstr (op[0], op[1], &dst, acc); /* get src */ - ProbeDstr (op[2], op[3], WA); /* test dst write */ - Write (op[3], dst.sign? C_MINUS: C_PLUS, L_BYTE, WA); - for (i = 1; i <= op[2]; i++) { /* loop thru chars */ - d = (dst.val[i / 8] >> ((i % 8) * 4)) & 0xF;/* get digit */ - c = d | C_ZERO; /* cvt to ASCII */ - Write ((op[3] + op[2] + 1 - i) & LMASK, c, L_BYTE, WA); - } - cc = SetCCDstr (op[2], &dst, 0); /* set cc's */ - R[0] = 0; - R[1] = op[1]; - R[2] = 0; - R[3] = op[3]; - return cc; - + case CVTPS: + if ((PSL & PSL_FPD) || (op[0] > 31) || (op[2] > 31)) + RSVD_OPND_FAULT; + ReadDstr (op[0], op[1], &dst, acc); /* get src */ + ProbeDstr (op[2], op[3], WA); /* test dst write */ + Write (op[3], dst.sign? C_MINUS: C_PLUS, L_BYTE, WA); + for (i = 1; i <= op[2]; i++) { /* loop thru chars */ + d = (dst.val[i / 8] >> ((i % 8) * 4)) & 0xF;/* get digit */ + c = d | C_ZERO; /* cvt to ASCII */ + Write ((op[3] + op[2] + 1 - i) & LMASK, c, L_BYTE, WA); + } + cc = SetCCDstr (op[2], &dst, 0); /* set cc's */ + R[0] = 0; + R[1] = op[1]; + R[2] = 0; + R[3] = op[3]; + return cc; + /* CVTTP Operands: - op[0:1] = source string descriptor - op[2] = table address - op[3:4] = dest string descriptor + op[0:1] = source string descriptor + op[2] = table address + op[3:4] = dest string descriptor Condition codes: - NZV = set from result - C = 0 + NZV = set from result + C = 0 Registers: - R0 = 0 - R1 = addr of source string - R2 = 0 - R3 = addr of dest string + R0 = 0 + R1 = addr of source string + R2 = 0 + R3 = addr of dest string */ -case CVTTP: - if ((PSL & PSL_FPD) || (op[0] > 31) || (op[3] > 31)) - RSVD_OPND_FAULT; - dst = Dstr_zero; /* clear result */ - for (i = 1; i <= op[0]; i++) { /* loop thru char */ - c = Read ((op[1] + op[0] - i) & LMASK, L_BYTE, RA); /* read char */ - if (i != 1) { /* normal byte? */ - if ((c < C_ZERO) || (c > C_NINE)) /* valid digit? */ - RSVD_OPND_FAULT; - d = c & 0xF; - } - else { /* highest byte */ - t = Read ((op[2] + c) & LMASK, L_BYTE, RA); /* xlate */ - d = (t >> 4) & 0xF; /* digit */ - t = t & 0xF; /* sign */ - if ((d > 0x9) || (t < 0xA)) RSVD_OPND_FAULT; - if ((t == 0xB) || (t == 0xD)) dst.sign = 1; - } - dst.val[i / 8] = dst.val[i / 8] | (d << ((i % 8) * 4)); - } - TestDstr (&dst); /* correct -0 */ - cc = WriteDstr (op[3], op[4], &dst, 0, acc); /* write result */ - R[0] = 0; - R[1] = op[1]; - R[2] = 0; - R[3] = op[4]; - return cc; - + case CVTTP: + if ((PSL & PSL_FPD) || (op[0] > 31) || (op[3] > 31)) + RSVD_OPND_FAULT; + dst = Dstr_zero; /* clear result */ + for (i = 1; i <= op[0]; i++) { /* loop thru char */ + c = Read ((op[1] + op[0] - i) & LMASK, L_BYTE, RA); /* read char */ + if (i != 1) { /* normal byte? */ + if ((c < C_ZERO) || (c > C_NINE)) /* valid digit? */ + RSVD_OPND_FAULT; + d = c & 0xF; + } + else { /* highest byte */ + t = Read ((op[2] + c) & LMASK, L_BYTE, RA); /* xlate */ + d = (t >> 4) & 0xF; /* digit */ + t = t & 0xF; /* sign */ + if ((d > 0x9) || (t < 0xA)) RSVD_OPND_FAULT; + if ((t == 0xB) || (t == 0xD)) dst.sign = 1; + } + dst.val[i / 8] = dst.val[i / 8] | (d << ((i % 8) * 4)); + } + TestDstr (&dst); /* correct -0 */ + cc = WriteDstr (op[3], op[4], &dst, 0, acc); /* write result */ + R[0] = 0; + R[1] = op[1]; + R[2] = 0; + R[3] = op[4]; + return cc; + /* CVTPT Operands: - op[0:1] = source string descriptor - op[2] = table address - op[3:4] = dest string descriptor + op[0:1] = source string descriptor + op[2] = table address + op[3:4] = dest string descriptor Condition codes: - NZV = set from result - C = 0 + NZV = set from result + C = 0 Registers: - R0 = 0 - R1 = addr of source string - R2 = 0 - R3 = addr of dest string + R0 = 0 + R1 = addr of source string + R2 = 0 + R3 = addr of dest string */ -case CVTPT: - if ((PSL & PSL_FPD) || (op[0] > 31) || (op[3] > 31)) - RSVD_OPND_FAULT; - ReadDstr (op[0], op[1], &dst, acc); /* get source */ - ProbeDstr (op[3], op[4], WA); /* test writeability */ - for (i = 1; i <= op[3]; i++) { /* loop thru chars */ - if (i != 1) { /* not last? */ - d = (dst.val[i / 8] >> ((i % 8) * 4)) & 0xF; /* get digit */ - c = d + C_ZERO; /* convert */ - } - else { /* translate last */ - t = Read ((op[1] + (op[0] / 2)) & LMASK, L_BYTE, RA); - c = Read ((op[2] + t) & LMASK, L_BYTE, RA); - } - Write ((op[4] + op[3] - i) & LMASK, c, L_BYTE, WA); - } - cc = SetCCDstr (op[3], &dst, 0); /* set cc's */ - R[0] = 0; - R[1] = op[1]; - R[2] = 0; - R[3] = op[4]; - return cc; - + case CVTPT: + if ((PSL & PSL_FPD) || (op[0] > 31) || (op[3] > 31)) + RSVD_OPND_FAULT; + ReadDstr (op[0], op[1], &dst, acc); /* get source */ + ProbeDstr (op[3], op[4], WA); /* test writeability */ + for (i = 1; i <= op[3]; i++) { /* loop thru chars */ + if (i != 1) { /* not last? */ + d = (dst.val[i / 8] >> ((i % 8) * 4)) & 0xF; /* get digit */ + c = d + C_ZERO; /* convert */ + } + else { /* translate last */ + t = Read ((op[1] + (op[0] / 2)) & LMASK, L_BYTE, RA); + c = Read ((op[2] + t) & LMASK, L_BYTE, RA); + } + Write ((op[4] + op[3] - i) & LMASK, c, L_BYTE, WA); + } + cc = SetCCDstr (op[3], &dst, 0); /* set cc's */ + R[0] = 0; + R[1] = op[1]; + R[2] = 0; + R[3] = op[4]; + return cc; + /* EDITPC Operands: - op[0:1] = source string descriptor - op[2] = pattern string address - op[3] = dest string address + op[0:1] = source string descriptor + op[2] = pattern string address + op[3] = dest string address Condition codes: - N = source is negative - Z = source is zero - V = significant digits lost - C = significant digits seen + N = source is negative + Z = source is zero + V = significant digits lost + C = significant digits seen Registers at packup: - R0<31:16> = -count of source zeroes to supply - R0<15:0> = remaining source length - R1 = source address - R2<31:24> = delta PC - R2<15:8> = sign char - R2<7:0> = fill char - R3 = pattern string address - R4 = original source length - R5 = dest string addr + R0<31:16> = -count of source zeroes to supply + R0<15:0> = remaining source length + R1 = source address + R2<31:24> = delta PC + R2<15:8> = sign char + R2<7:0> = fill char + R3 = pattern string address + R4 = original source length + R5 = dest string addr Registers at end: - R0 = source length - R1 = source addr - R2 = 0 - R3 = addr of byte containing EO$END - R4 = 0 - R5 = addr of end of dst string + 1 + R0 = source length + R1 = source addr + R2 = 0 + R3 = addr of byte containing EO$END + R4 = 0 + R5 = addr of end of dst string + 1 Fault and abort conditions for EDITPC are complicated. In general: - It is safe to take a memory management fault on the read of @@ -962,169 +961,170 @@ case CVTPT: until all memory operations are complete. */ -case EDITPC: - if (PSL & PSL_FPD) { /* FPD set? */ - SETPC (fault_PC + STR_GETDPC (R[2])); /* reset PC */ - fill = ED_GETFILL (R[2]); /* get fill */ - sign = ED_GETSIGN (R[2]); /* get sign */ - R[0] = R[0] & ~0xFFE0; /* src len <= 31 */ - } - else { /* new instr */ - if (op[0] > 31) RSVD_OPND_FAULT; /* lnt > 31? */ - t = Read ((op[1] + (op[0] / 2)) & LMASK, L_BYTE, RA) & 0xF; - if ((t == 0xB) || (t == 0xD)) { - cc = CC_N | CC_Z; - sign = C_MINUS; - } - else { - cc = CC_Z; - sign = C_SPACE; - } - fill = C_SPACE; - R[0] = R[4] = op[0]; /* src len */ - R[1] = op[1]; /* src addr */ - R[2] = STR_PACK (0, (sign << ED_V_SIGN) | (fill << ED_V_FILL)); - /* delta PC, sign, fill */ - R[3] = op[2]; /* pattern */ - R[5] = op[3]; /* dst addr */ - PSL = PSL | PSL_FPD; /* set FPD */ - } - for ( ;; ) { /* loop thru pattern */ - pop = Read (R[3], L_BYTE, RA); /* rd pattern op */ - if (pop == EO_END) break; /* end? */ - if (pop & EO_RPT_FLAG) { /* repeat class? */ - rpt = pop & EO_RPT_MASK; /* isolate count */ - if (rpt == 0) RSVD_OPND_FAULT; /* can't be zero */ - pop = pop & ~EO_RPT_MASK; /* isolate op */ - } - switch (pop) { /* case on op */ - case EO_END_FLOAT: /* end float */ - if (!(cc & CC_C)) { /* not signif? */ - Write (R[5], sign, L_BYTE, WA); /* write sign */ - R[5] = (R[5] + 1) & LMASK; /* now fault safe */ - cc = cc | CC_C; /* set signif */ - } - break; - case EO_CLR_SIGNIF: /* clear signif */ - cc = cc & ~CC_C; /* clr C */ - break; - case EO_SET_SIGNIF: /* set signif */ - cc = cc | CC_C; /* set C */ - break; - case EO_STORE_SIGN: /* store sign */ - Write (R[5], sign, L_BYTE, WA); /* write sign */ - R[5] = (R[5] + 1) & LMASK; /* now fault safe */ - break; - case EO_LOAD_FILL: /* load fill */ - fill = Read ((R[3] + 1) & LMASK, L_BYTE, RA); - R[2] = ED_PUTFILL (R[2], fill); /* now fault safe */ - R[3]++; - break; - case EO_LOAD_SIGN: /* load sign */ - sign = edit_read_sign (acc); - break; - case EO_LOAD_PLUS: /* load sign if + */ - if (!(cc & CC_N)) sign = edit_read_sign (acc); - break; - case EO_LOAD_MINUS: /* load sign if - */ - if (cc & CC_N) sign = edit_read_sign (acc); - break; - case EO_INSERT: /* insert char */ - c = Read ((R[3] + 1) & LMASK, L_BYTE, RA); - Write (R[5], ((cc & CC_C)? c: sign), L_BYTE, WA); - R[5] = (R[5] + 1) & LMASK; /* now fault safe */ - R[3]++; - break; - case EO_BLANK_ZERO: /* blank zero */ - t = Read ((R[3] + 1) & LMASK, L_BYTE, RA); - if (t == 0) RSVD_OPND_FAULT; - while (t--) /* repeat and blank */ - Write ((R[5] - t) & LMASK, fill, L_BYTE, WA); - R[3]++; /* now fault safe */ - break; - case EO_REPL_SIGN: /* replace sign */ - t = Read ((R[3] + 1) & LMASK, L_BYTE, RA); - if (t == 0) RSVD_OPND_FAULT; - if (cc & CC_Z) - Write ((R[5] - t) & LMASK, fill, L_BYTE, WA); - R[3]++; /* now fault safe */ - break; - case EO_ADJUST_LNT: /* adjust length */ - t = Read ((R[3] + 1) & LMASK, L_BYTE, RA); - if ((t == 0) || (t > 31)) RSVD_OPND_FAULT; - R[0] = R[0] & WMASK; /* clr old ld zero */ - if (R[0] > t) { /* decrease */ - ncc = cc; /* copy cc's */ - for (i = 0; i < (R[0] - t); i++) { /* loop thru src */ - d = edit_read_src (i, acc); /* get nibble */ - if (d) ncc = (ncc | CC_V | CC_C) & ~CC_Z; - } /* end for */ - cc = ncc; /* now fault safe */ - edit_adv_src (R[0] - t); /* adv src ptr */ - } /* end else */ - else R[0] = R[0] | (((R[0] - t) & WMASK) << 16); - R[3]++; - break; - case EO_FILL: /* fill */ - for (i = 0; i < rpt; i++) /* fill string */ - Write ((R[5] + i) & LMASK, fill, L_BYTE, WA); - R[5] = (R[5] + rpt) & LMASK; /* now fault safe */ - break; - case EO_MOVE: - ncc = cc; /* copy cc's */ - for (i = 0; i < rpt; i++) { /* for repeat */ - d = edit_read_src (i, acc); /* get nibble */ - if (d) ncc = (ncc | CC_C) & ~CC_Z; /* test for non-zero */ - c = (ncc & CC_C)? (d | 0x30): fill; /* test for signif */ - Write ((R[5] + i) & LMASK, c, L_BYTE, WA); - } /* end for */ - cc = ncc; /* now fault safe */ - edit_adv_src (rpt); /* advance src */ - R[5] = (R[5] + rpt) & LMASK; /* advance dst */ - break; - case EO_FLOAT: - ncc = cc; /* copy cc's */ - for (i = j = 0; i < rpt; i++, j++) { /* for repeat */ - d = edit_read_src (i, acc); /* get nibble */ - if (d && !(ncc & CC_C)) { /* nz, signif clear? */ - Write ((R[5] + j) & LMASK, sign, L_BYTE, WA); - ncc = (ncc | CC_C) & ~CC_Z; /* set signif */ - j++; /* extra dst char */ - } /* end if */ - c = (ncc & CC_C)? (d | 0x30): fill; /* test for signif */ - Write ((R[5] + j) & LMASK, c, L_BYTE, WA); - } /* end for */ - cc = ncc; /* now fault safe */ - edit_adv_src (rpt); /* advance src */ - R[5] = (R[5] + j) & LMASK; /* advance dst */ - break; - default: /* undefined */ - RSVD_OPND_FAULT; - } /* end case pattern */ - R[3] = (R[3] + 1) & LMASK; /* next pattern byte */ - } /* end for pattern */ - if (R[0]) RSVD_OPND_FAULT; /* pattern too short */ - PSL = PSL & ~PSL_FPD; /* clear FPD */ - if (cc & CC_Z) cc = cc & ~CC_N; /* zero? clear n */ - if ((cc & CC_V) && (PSL & PSW_DV)) SET_TRAP (TRAP_DECOVF); - R[0] = R[4]; /* restore src len */ - R[1] = R[1] - (R[0] >> 1); /* restore src addr */ - R[2] = R[4] = 0; - return cc; + case EDITPC: + if (PSL & PSL_FPD) { /* FPD set? */ + SETPC (fault_PC + STR_GETDPC (R[2])); /* reset PC */ + fill = ED_GETFILL (R[2]); /* get fill */ + sign = ED_GETSIGN (R[2]); /* get sign */ + R[0] = R[0] & ~0xFFE0; /* src len <= 31 */ + } + else { /* new instr */ + if (op[0] > 31) RSVD_OPND_FAULT; /* lnt > 31? */ + t = Read ((op[1] + (op[0] / 2)) & LMASK, L_BYTE, RA) & 0xF; + if ((t == 0xB) || (t == 0xD)) { + cc = CC_N | CC_Z; + sign = C_MINUS; + } + else { + cc = CC_Z; + sign = C_SPACE; + } + fill = C_SPACE; + R[0] = R[4] = op[0]; /* src len */ + R[1] = op[1]; /* src addr */ + R[2] = STR_PACK (0, (sign << ED_V_SIGN) | (fill << ED_V_FILL)); + /* delta PC, sign, fill */ + R[3] = op[2]; /* pattern */ + R[5] = op[3]; /* dst addr */ + PSL = PSL | PSL_FPD; /* set FPD */ + } + for ( ;; ) { /* loop thru pattern */ + pop = Read (R[3], L_BYTE, RA); /* rd pattern op */ + if (pop == EO_END) break; /* end? */ + if (pop & EO_RPT_FLAG) { /* repeat class? */ + rpt = pop & EO_RPT_MASK; /* isolate count */ + if (rpt == 0) RSVD_OPND_FAULT; /* can't be zero */ + pop = pop & ~EO_RPT_MASK; /* isolate op */ + } + switch (pop) { /* case on op */ + case EO_END_FLOAT: /* end float */ + if (!(cc & CC_C)) { /* not signif? */ + Write (R[5], sign, L_BYTE, WA); /* write sign */ + R[5] = (R[5] + 1) & LMASK; /* now fault safe */ + cc = cc | CC_C; /* set signif */ + } + break; + case EO_CLR_SIGNIF: /* clear signif */ + cc = cc & ~CC_C; /* clr C */ + break; + case EO_SET_SIGNIF: /* set signif */ + cc = cc | CC_C; /* set C */ + break; + case EO_STORE_SIGN: /* store sign */ + Write (R[5], sign, L_BYTE, WA); /* write sign */ + R[5] = (R[5] + 1) & LMASK; /* now fault safe */ + break; + case EO_LOAD_FILL: /* load fill */ + fill = Read ((R[3] + 1) & LMASK, L_BYTE, RA); + R[2] = ED_PUTFILL (R[2], fill); /* now fault safe */ + R[3]++; + break; + case EO_LOAD_SIGN: /* load sign */ + sign = edit_read_sign (acc); + break; + case EO_LOAD_PLUS: /* load sign if + */ + if (!(cc & CC_N)) sign = edit_read_sign (acc); + break; + case EO_LOAD_MINUS: /* load sign if - */ + if (cc & CC_N) sign = edit_read_sign (acc); + break; + case EO_INSERT: /* insert char */ + c = Read ((R[3] + 1) & LMASK, L_BYTE, RA); + Write (R[5], ((cc & CC_C)? c: sign), L_BYTE, WA); + R[5] = (R[5] + 1) & LMASK; /* now fault safe */ + R[3]++; + break; + case EO_BLANK_ZERO: /* blank zero */ + t = Read ((R[3] + 1) & LMASK, L_BYTE, RA); + if (t == 0) RSVD_OPND_FAULT; + while (t--) /* repeat and blank */ + Write ((R[5] - t) & LMASK, fill, L_BYTE, WA); + R[3]++; /* now fault safe */ + break; + case EO_REPL_SIGN: /* replace sign */ + t = Read ((R[3] + 1) & LMASK, L_BYTE, RA); + if (t == 0) RSVD_OPND_FAULT; + if (cc & CC_Z) + Write ((R[5] - t) & LMASK, fill, L_BYTE, WA); + R[3]++; /* now fault safe */ + break; + case EO_ADJUST_LNT: /* adjust length */ + t = Read ((R[3] + 1) & LMASK, L_BYTE, RA); + if ((t == 0) || (t > 31)) RSVD_OPND_FAULT; + R[0] = R[0] & WMASK; /* clr old ld zero */ + if (R[0] > t) { /* decrease */ + ncc = cc; /* copy cc's */ + for (i = 0; i < (R[0] - t); i++) { /* loop thru src */ + d = edit_read_src (i, acc); /* get nibble */ + if (d) ncc = (ncc | CC_V | CC_C) & ~CC_Z; + } /* end for */ + cc = ncc; /* now fault safe */ + edit_adv_src (R[0] - t); /* adv src ptr */ + } /* end else */ + else R[0] = R[0] | (((R[0] - t) & WMASK) << 16); + R[3]++; + break; + case EO_FILL: /* fill */ + for (i = 0; i < rpt; i++) /* fill string */ + Write ((R[5] + i) & LMASK, fill, L_BYTE, WA); + R[5] = (R[5] + rpt) & LMASK; /* now fault safe */ + break; + case EO_MOVE: + ncc = cc; /* copy cc's */ + for (i = 0; i < rpt; i++) { /* for repeat */ + d = edit_read_src (i, acc); /* get nibble */ + if (d) ncc = (ncc | CC_C) & ~CC_Z; /* test for non-zero */ + c = (ncc & CC_C)? (d | 0x30): fill; /* test for signif */ + Write ((R[5] + i) & LMASK, c, L_BYTE, WA); + } /* end for */ + cc = ncc; /* now fault safe */ + edit_adv_src (rpt); /* advance src */ + R[5] = (R[5] + rpt) & LMASK; /* advance dst */ + break; + case EO_FLOAT: + ncc = cc; /* copy cc's */ + for (i = j = 0; i < rpt; i++, j++) { /* for repeat */ + d = edit_read_src (i, acc); /* get nibble */ + if (d && !(ncc & CC_C)) { /* nz, signif clear? */ + Write ((R[5] + j) & LMASK, sign, L_BYTE, WA); + ncc = (ncc | CC_C) & ~CC_Z; /* set signif */ + j++; /* extra dst char */ + } /* end if */ + c = (ncc & CC_C)? (d | 0x30): fill; /* test for signif */ + Write ((R[5] + j) & LMASK, c, L_BYTE, WA); + } /* end for */ + cc = ncc; /* now fault safe */ + edit_adv_src (rpt); /* advance src */ + R[5] = (R[5] + j) & LMASK; /* advance dst */ + break; + default: /* undefined */ + RSVD_OPND_FAULT; + } /* end case pattern */ + R[3] = (R[3] + 1) & LMASK; /* next pattern byte */ + } /* end for pattern */ + if (R[0]) RSVD_OPND_FAULT; /* pattern too short */ + PSL = PSL & ~PSL_FPD; /* clear FPD */ + if (cc & CC_Z) cc = cc & ~CC_N; /* zero? clear n */ + if ((cc & CC_V) && (PSL & PSW_DV)) SET_TRAP (TRAP_DECOVF); + R[0] = R[4]; /* restore src len */ + R[1] = R[1] - (R[0] >> 1); /* restore src addr */ + R[2] = R[4] = 0; + return cc; -default: - RSVD_INST_FAULT; - } /* end case op */ + default: + RSVD_INST_FAULT; + } + /* end case op */ return cc; } - + /* Get packed decimal string Arguments: - lnt = decimal string length - adr = decimal string address - src = decimal string structure - acc = access mode + lnt = decimal string length + adr = decimal string address + src = decimal string structure + acc = access mode The routine returns the length in int32's of the non-zero part of the string. @@ -1137,42 +1137,43 @@ int32 ReadDstr (int32 lnt, int32 adr, DSTR *src, int32 acc) { int32 c, i, end, t; -*src = Dstr_zero; /* clear result */ -end = lnt / 2; /* last byte */ -for (i = 0; i <= end; i++) { /* loop thru string */ - c = Read ((adr + end - i) & LMASK, L_BYTE, RA); /* get byte */ - if (i == 0) { /* sign char? */ - t = c & 0xF; /* save sign */ - c = c & 0xF0; } /* erase sign */ - if ((i == end) && ((lnt & 1) == 0)) c = c & 0xF; - if (((c & 0xF0) > 0x90) || /* check hi digit */ - ((c & 0x0F) > 0x09)) RSVD_OPND_FAULT; /* 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 */ -return TestDstr (src); /* clean -0 */ +*src = Dstr_zero; /* clear result */ +end = lnt / 2; /* last byte */ +for (i = 0; i <= end; i++) { /* loop thru string */ + c = Read ((adr + end - i) & LMASK, L_BYTE, RA); /* get byte */ + if (i == 0) { /* sign char? */ + t = c & 0xF; /* save sign */ + c = c & 0xF0; /* erase sign */ + } + if ((i == end) && ((lnt & 1) == 0)) c = c & 0xF; + if (((c & 0xF0) > 0x90) || /* check hi digit */ + ((c & 0x0F) > 0x09)) RSVD_OPND_FAULT; /* 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 */ +return TestDstr (src); /* clean -0 */ } - + /* Store decimal string Arguments: - lnt = decimal string length - adr = decimal string address - dst = decimal string structure - V = initial overflow flag - acc = access mode + lnt = decimal string length + adr = decimal string address + dst = decimal string structure + V = initial overflow flag + acc = access mode Returns condition codes. PSL.NZ are also set to their proper values PSL.V will be set on overflow; it must be initialized elsewhere - (to allow for external overflow calculations) + (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, and the result - is non-zero or there was overflow - - PSL sign is negative if input is negative, and the result is - non-zero + - Stored sign is negative if input is negative, and the result + is non-zero or there was overflow + - PSL sign is negative if input is negative, and the result is + non-zero Thus, the stored sign and the PSL sign will differ in one case: a negative zero generated by overflow is stored with a negative sign, but PSL.N is clear @@ -1182,26 +1183,26 @@ int32 WriteDstr (int32 lnt, int32 adr, DSTR *dst, int32 pslv, int32 acc) { int32 c, i, cc, end; -end = lnt / 2; /* end of string */ -ProbeDstr (end, adr, WA); /* test writeability */ -cc = SetCCDstr (lnt, dst, pslv); /* set cond codes */ -dst->val[0] = dst->val[0] | 0xC | dst->sign; /* set sign */ -for (i = 0; i <= end; i++) { /* store string */ - c = (dst->val[i / 4] >> ((i % 4) * 8)) & 0xFF; - Write ((adr + end - i) & LMASK, c, L_BYTE, WA); - } /* end for */ +end = lnt / 2; /* end of string */ +ProbeDstr (end, adr, WA); /* test writeability */ +cc = SetCCDstr (lnt, dst, pslv); /* set cond codes */ +dst->val[0] = dst->val[0] | 0xC | dst->sign; /* set sign */ +for (i = 0; i <= end; i++) { /* store string */ + c = (dst->val[i / 4] >> ((i % 4) * 8)) & 0xFF; + Write ((adr + end - i) & LMASK, c, L_BYTE, WA); + } /* end for */ return cc; } /* Set CC for decimal string Arguments: - lnt = string length - dst = decimal string structure - pslv = initial V + lnt = string length + dst = decimal string structure + pslv = initial V Output: - cc = condition codes + cc = condition codes */ int32 SetCCDstr (int32 lnt, DSTR *dst, int32 pslv) @@ -1209,20 +1210,21 @@ int32 SetCCDstr (int32 lnt, DSTR *dst, int32 pslv) int32 psln, pslz, i, limit; uint32 mask; static uint32 masktab[8] = { - 0xFFFFFFF0, 0xFFFFFF00, 0xFFFFF000, 0xFFFF0000, - 0xFFF00000, 0xFF000000, 0xF0000000, 0x00000000 }; + 0xFFFFFFF0, 0xFFFFFF00, 0xFFFFF000, 0xFFFF0000, + 0xFFF00000, 0xFF000000, 0xF0000000, 0x00000000 + }; -mask = 0; /* can't ovflo */ -pslz = 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) pslv = 1; /* test for ovflo */ - if (dst->val[i] = dst->val[i] & ~mask) pslz = 0;/* test nz */ - } +mask = 0; /* can't ovflo */ +pslz = 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) pslv = 1; /* test for ovflo */ + if (dst->val[i] = dst->val[i] & ~mask) pslz = 0; /* test nz */ + } dst->sign = dst->sign & ~(pslz & ~pslv); -psln = dst->sign & ~pslz; /* N = sign, if ~zero */ +psln = dst->sign & ~pslz; /* N = sign, if ~zero */ if (pslv && (PSL & PSW_DV)) SET_TRAP (TRAP_DECOVF); return (psln? CC_N: 0) | (pslz? CC_Z: 0) | (pslv? CC_V: 0); } @@ -1235,15 +1237,15 @@ Read (addr, L_BYTE, acc); Read ((addr + lnt) & LMASK, L_BYTE, acc); return; } - + /* Add decimal string magnitudes Arguments: - s1 = src1 decimal string - s2 = src2 decimal string - ds = dest decimal string - cy = carry in - Output = 1 if carry, 0 if no carry + s1 = src1 decimal string + s2 = src2 decimal string + ds = dest decimal string + cy = carry in + Output = 1 if carry, 0 if no carry This algorithm courtesy Anton Chernoff, circa 1992 or even earlier @@ -1251,11 +1253,11 @@ return; carry is fixed; each parenthesized item is a 4b digit. Assume we are adding: - (a)(b) I - + (x)(y) J + (a)(b) I + + (x)(y) J First compute I^J: - (a^x)(b^y) TMP + (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 carry, since the low bit of the @@ -1263,7 +1265,7 @@ return; 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 + (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. @@ -1279,26 +1281,26 @@ int32 AddDstr (DSTR *s1, DSTR *s2, DSTR *ds, int32 cy) int32 i; uint32 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)) & LMASK; /* final result */ - } +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)) & LMASK; /* final result */ + } return cy; } - + /* Subtract decimal string magnitudes Arguments: - s1 = src1 decimal string - s2 = src2 decimal string - ds = dest decimal string - Outputs: s2 - s1 in ds + s1 = src1 decimal string + s2 = src2 decimal string + ds = dest decimal string + Outputs: s2 - s1 in ds Note: the routine assumes that s1 <= s2 @@ -1309,18 +1311,18 @@ void SubDstr (DSTR *s1, DSTR *s2, DSTR *ds) int32 i; DSTR compl; -for (i = 0; i < DSTRLNT; i++) /* 10's comp s2 */ - compl.val[i] = 0x99999999 - s1->val[i]; -AddDstr (&compl, s2, ds, 1); /* s1 + ~s2 + 1 */ +for (i = 0; i < DSTRLNT; i++) /* 10's comp s2 */ + compl.val[i] = 0x99999999 - s1->val[i]; +AddDstr (&compl, s2, ds, 1); /* s1 + ~s2 + 1 */ return; } /* Compare decimal string magnitudes Arguments: - s1 = src1 decimal string - s2 = src2 decimal string - Output = 1 if >, 0 if =, -1 if < + s1 = src1 decimal string + s2 = src2 decimal string + Output = 1 if >, 0 if =, -1 if < */ int32 CmpDstr (DSTR *s1, DSTR *s2) @@ -1328,16 +1330,16 @@ 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; - } + 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 + dsrc = decimal string structure Returns the non-zero length of the string, in int32 units If the string is zero, the sign is cleared @@ -1355,8 +1357,8 @@ return 0; /* Get exact length of decimal string Arguments: - dsrc = decimal string structure - nz = result from TestDstr + dsrc = decimal string structure + nz = result from TestDstr */ int32 LntDstr (DSTR *dsrc, int32 nz) @@ -1364,19 +1366,19 @@ int32 LntDstr (DSTR *dsrc, int32 nz) int32 i; for (i = 7; i > 0; i--) { - if ((dsrc->val[nz - 1] >> (i * 4)) & 0xF) break; - } + 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 + 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 + guarantees that the largest multiple won't overflow Also note that mtable[0] is not filled in */ @@ -1386,15 +1388,15 @@ int32 (i); mtable[1] = *dsrc; for (i = 2; i < 10; i++) - AddDstr (&mtable[1], &mtable[i-1], &mtable[i], 0); + AddDstr (&mtable[1], &mtable[i-1], &mtable[i], 0); return; } - + /* Word shift right Arguments: - dsrc = decimal string structure - sc = shift count + dsrc = decimal string structure + sc = shift count */ void WordRshift (DSTR *dsrc, int32 sc) @@ -1402,19 +1404,19 @@ 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; - } - } + 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 + dsrc = decimal string structure + sc = shift count */ int32 WordLshift (DSTR *dsrc, int32 sc) @@ -1423,21 +1425,21 @@ 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; - } - } + 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 + dsrc = decimal string structure + sc = shift count + cin = carry in */ uint32 NibbleRshift (DSTR *dsrc, int32 sc, uint32 cin) @@ -1445,24 +1447,24 @@ uint32 NibbleRshift (DSTR *dsrc, int32 sc, uint32 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; - } + 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 + dsrc = decimal string structure + sc = shift count + cin = carry in */ uint32 NibbleLshift (DSTR *dsrc, int32 sc, uint32 cin) @@ -1470,26 +1472,26 @@ uint32 NibbleLshift (DSTR *dsrc, int32 sc, uint32 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; - } + 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; } /* Do 4b of CRC calculation Arguments: - crc = current CRC ^ char - tbl = 16 lw table base + crc = current CRC ^ char + tbl = 16 lw table base Output: - new CRC + new CRC */ int32 do_crc_4b (int32 crc, int32 tbl, int32 acc) @@ -1508,29 +1510,29 @@ int32 edit_read_src (int32 inc, int32 acc) { int32 c, r0, r1; -if (R[0] & LSIGN) { /* ld zeroes? */ - r0 = (R[0] + (inc << 16)) & LMASK; /* retire increment */ - if (r0 & LSIGN) return 0; /* more? return 0 */ - inc = (r0 >> 16) & 0x1F; /* effective inc */ - } -r1 = (R[1] + (inc / 2) + ((~R[0] & inc) & 1)) & LMASK; /* eff addr */ -r0 = (R[0] - inc) & 0x1F; /* eff lnt left */ -if (r0 == 0) { /* nothing left? */ - R[0] = -1; /* out of input */ - RSVD_OPND_FAULT; - } +if (R[0] & LSIGN) { /* ld zeroes? */ + r0 = (R[0] + (inc << 16)) & LMASK; /* retire increment */ + if (r0 & LSIGN) return 0; /* more? return 0 */ + inc = (r0 >> 16) & 0x1F; /* effective inc */ + } +r1 = (R[1] + (inc / 2) + ((~R[0] & inc) & 1)) & LMASK; /* eff addr */ +r0 = (R[0] - inc) & 0x1F; /* eff lnt left */ +if (r0 == 0) { /* nothing left? */ + R[0] = -1; /* out of input */ + RSVD_OPND_FAULT; + } c = Read (r1, L_BYTE, RA); return (((r0 & 1)? (c >> 4): c) & 0xF); } void edit_adv_src (int32 inc) { -if (R[0] & LSIGN) { /* ld zeroes? */ - R[0] = (R[0] + (inc << 16)) & LMASK; /* retire 0's */ - if (R[0] & LSIGN) return; /* more to do? */ - inc = (R[0] >> 16) & 0x1F; /* get excess */ - if (inc == 0) return; /* more to do? */ - } +if (R[0] & LSIGN) { /* ld zeroes? */ + R[0] = (R[0] + (inc << 16)) & LMASK; /* retire 0's */ + if (R[0] & LSIGN) return; /* more to do? */ + inc = (R[0] >> 16) & 0x1F; /* get excess */ + if (inc == 0) return; /* more to do? */ + } R[1] = (R[1] + (inc / 2) + ((~R[0] & inc) & 1)) & LMASK;/* retire src */ R[0] = (R[0] - inc) & 0x1F; return; @@ -1540,12 +1542,12 @@ int32 edit_read_sign (int32 acc) { int32 sign; -sign = Read ((R[3] + 1) & LMASK, L_BYTE, RA); /* read */ -R[2] = ED_PUTSIGN (R[2], sign); /* now fault safe */ +sign = Read ((R[3] + 1) & LMASK, L_BYTE, RA); /* read */ +R[2] = ED_PUTSIGN (R[2], sign); /* now fault safe */ R[3] = (R[3] + 1) & LMASK; return sign; } - + #else extern int32 R[16]; @@ -1563,13 +1565,13 @@ extern int32 ReadLP (uint32 pa); /* CIS instructions - invoke emulator interface - opnd[0:5] = six operands to be pushed (if PSL = 0) - cc = condition codes - opc = opcode + 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. + on stack, vector thru SCB. In both cases, the exception occurs in the current mode. */ @@ -1577,30 +1579,33 @@ int32 op_cis (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 { if (opc == CVTPL) /* CVTPL? .wl */ - opnd[2] = (opnd[2] >= 0)? ~opnd[2]: opnd[3]; - 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); } +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 { + if (opc == CVTPL) /* CVTPL? .wl */ + opnd[2] = (opnd[2] >= 0)? ~opnd[2]: opnd[3]; + 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 */ +JUMP (vec & ~03); /* set new PC */ +return 0; /* set new cc's */ } #endif diff --git a/VAX/vax_cmode.c b/VAX/vax_cmode.c index 95cae643..448544c3 100644 --- a/VAX/vax_cmode.c +++ b/VAX/vax_cmode.c @@ -1,6 +1,6 @@ /* vax_cmode.c: VAX compatibility mode - Copyright (c) 2004, Robert M Supnik + Copyright (c) 2004-2005, 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"), @@ -19,39 +19,39 @@ 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 + 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. On a full VAX, this module implements PDP-11 compatibility mode. On a subset VAX, this module forces a fault if REI attempts to set PSL. - 24-Aug-04 RMS Cloned from PDP-11 CPU + 24-Aug-04 RMS Cloned from PDP-11 CPU In compatibility mode, the Istream prefetch mechanism is not used. The prefetcher will be explicitly resynchronized through intexc on any exit from compatibility mode. */ - + #include "vax_defs.h" #if defined (FULL_VAX) -#define RdMemB(a) Read (a, L_BYTE, RA) -#define RdMemMB(a) Read (a, L_BYTE, WA) -#define WrMemB(d,a) Write (a, d, L_BYTE, WA) -#define BRANCH_F(x) CMODE_JUMP ((PC + (((x) + (x)) & BMASK)) & WMASK) -#define BRANCH_B(x) CMODE_JUMP ((PC + (((x) + (x)) | 0177400)) & WMASK) -#define CC_XOR_NV(x) ((((x) & CC_N) != 0) ^ (((x) & CC_V) != 0)) -#define CC_XOR_NC(x) ((((x) & CC_N) != 0) ^ (((x) & CC_C) != 0)) +#define RdMemB(a) Read (a, L_BYTE, RA) +#define RdMemMB(a) Read (a, L_BYTE, WA) +#define WrMemB(d,a) Write (a, d, L_BYTE, WA) +#define BRANCH_F(x) CMODE_JUMP ((PC + (((x) + (x)) & BMASK)) & WMASK) +#define BRANCH_B(x) CMODE_JUMP ((PC + (((x) + (x)) | 0177400)) & WMASK) +#define CC_XOR_NV(x) ((((x) & CC_N) != 0) ^ (((x) & CC_V) != 0)) +#define CC_XOR_NC(x) ((((x) & CC_N) != 0) ^ (((x) & CC_C) != 0)) extern int32 R[16]; extern int32 PSL; extern int32 trpirq; extern int32 p1; extern int32 fault_PC; -extern int32 recq[]; /* recovery queue */ -extern int32 recqptr; /* recq pointer */ +extern int32 recq[]; /* recovery queue */ +extern int32 recqptr; /* recq pointer */ extern int32 pcq[]; extern int32 pcq_p; extern int32 ibcnt, ppc; @@ -71,14 +71,14 @@ int32 RdRegB (int32 rn); int32 RdRegW (int32 rn); void WrRegB (int32 val, int32 rn); void WrRegW (int32 val, int32 rn); - + /* Validate PSL for compatibility mode */ t_bool BadCmPSL (int32 newpsl) { if ((newpsl & (PSL_FPD|PSL_IS|PSL_CUR|PSL_PRV|PSL_IPL)) != - ((USER << PSL_V_CUR) | (USER << PSL_V_PRV))) - return TRUE; + ((USER << PSL_V_CUR) | (USER << PSL_V_PRV))) + return TRUE; else return FALSE; } @@ -90,267 +90,260 @@ int32 IR, srcspec, dstspec, srcreg, dstreg, ea; int32 i, t, src, src2, dst, sign, oc; int32 acc = ACC_MASK (USER); -PC = PC & WMASK; /* PC must be 16b */ -if (sim_brk_summ && sim_brk_test (PC, SWMASK ('E'))) { /* breakpoint? */ - ABORT (STOP_IBKPT); } /* stop simulation */ -sim_interval = sim_interval - 1; /* count instr */ +PC = PC & WMASK; /* PC must be 16b */ +if (sim_brk_summ && sim_brk_test (PC, SWMASK ('E'))) { /* breakpoint? */ + ABORT (STOP_IBKPT); /* stop simulation */ + } +sim_interval = sim_interval - 1; /* count instr */ -IR = RdMemW (PC); /* fetch instruction */ -PC = (PC + 2) & WMASK; /* incr PC, mod 65k */ -srcspec = (IR >> 6) & 077; /* src, dst specs */ +IR = RdMemW (PC); /* fetch instruction */ +PC = (PC + 2) & WMASK; /* incr PC, mod 65k */ +srcspec = (IR >> 6) & 077; /* src, dst specs */ dstspec = IR & 077; -srcreg = (srcspec <= 07); /* src, dst = rmode? */ +srcreg = (srcspec <= 07); /* src, dst = rmode? */ dstreg = (dstspec <= 07); -switch ((IR >> 12) & 017) { /* decode IR<15:12> */ - +switch ((IR >> 12) & 017) { /* decode IR<15:12> */ + /* Opcode 0: no operands, specials, branches, JSR, SOPs */ -case 000: /* 00xxxx */ - switch ((IR >> 6) & 077) { /* decode IR<11:6> */ - case 000: /* 0000xx */ - switch (IR) { /* decode IR<5:0> */ - case 3: /* BPT */ - CMODE_FAULT (CMODE_BPT); - break; - case 4: /* IOT */ - CMODE_FAULT (CMODE_IOT); - break; - case 2: /* RTI */ - case 6: /* RTT */ - src = RdMemW (R[6] & WMASK); /* new PC */ - src2 = RdMemW ((R[6] + 2) & WMASK); /* new PSW */ - R[6] = (R[6] + 4) & WMASK; - cc = src2 & CC_MASK; /* update cc, T */ - if (src2 & PSW_T) PSL = PSL | PSW_T; - else PSL = PSL & ~PSW_T; - CMODE_JUMP (src); /* update PC */ - break; - default: /* undefined */ - CMODE_FAULT (CMODE_RSVI); - break; - } /* end switch IR */ - break; /* end case 0000xx */ - -/* Opcode 0: specials, continued */ + case 000: /* 00xxxx */ + switch ((IR >> 6) & 077) { /* decode IR<11:6> */ + case 000: /* 0000xx */ + switch (IR) { /* decode IR<5:0> */ + case 3: /* BPT */ + CMODE_FAULT (CMODE_BPT); + break; + case 4: /* IOT */ + CMODE_FAULT (CMODE_IOT); + break; + case 2: /* RTI */ + case 6: /* RTT */ + src = RdMemW (R[6] & WMASK); /* new PC */ + src2 = RdMemW ((R[6] + 2) & WMASK); /* new PSW */ + R[6] = (R[6] + 4) & WMASK; + cc = src2 & CC_MASK; /* update cc, T */ + if (src2 & PSW_T) PSL = PSL | PSW_T; + else PSL = PSL & ~PSW_T; + CMODE_JUMP (src); /* update PC */ + break; + default: /* undefined */ + CMODE_FAULT (CMODE_RSVI); + break; + } /* end switch IR */ + break; /* end case 0000xx */ + case 001: /* JMP */ + if (dstreg) CMODE_FAULT (CMODE_ILLI); /* mode 0 illegal */ + else { CMODE_JUMP (GeteaW (dstspec)); } + break; + case 002: /* 0002xx */ + if (IR < 000210) { /* RTS */ + dstspec = dstspec & 07; + if (dstspec != 7) { /* PC <- r */ + CMODE_JUMP (RdRegW (dstspec)); + } + dst = RdMemW (R[6]); /* t <- (sp)+ */ + R[6] = (R[6] + 2) & WMASK; + WrRegW (dst, dstspec); /* r <- t */ + break; /* end if RTS */ + } + if (IR < 000240) { /* [210:237] */ + CMODE_FAULT (CMODE_RSVI); + break; + } + if (IR < 000260) cc = cc & ~(IR & CC_MASK); /* clear CC */ + else cc = cc | (IR & CC_MASK); /* set CC */ + break; + case 003: /* SWAB */ + if (dstreg) src = RdRegW (dstspec); + else src = RdMemMW (ea = GeteaW (dstspec)); + dst = ((src & BMASK) << 8) | ((src >> 8) & BMASK); + if (dstreg) WrRegW (dst, dstspec); + else WrMemW (dst, ea); + CC_IIZZ_B ((dst & BMASK)); + break; + case 004: case 005: /* BR */ + BRANCH_F (IR); + break; + case 006: case 007: /* BR */ + BRANCH_B (IR); + break; + case 010: case 011: /* BNE */ + if ((cc & CC_Z) == 0) { BRANCH_F (IR); } + break; + case 012: case 013: /* BNE */ + if ((cc & CC_Z) == 0) { BRANCH_B (IR); } + break; + case 014: case 015: /* BEQ */ + if (cc & CC_Z) { BRANCH_F (IR); } + break; + case 016: case 017: /* BEQ */ + if (cc & CC_Z) { BRANCH_B (IR); } + break; + case 020: case 021: /* BGE */ + if (CC_XOR_NV (cc) == 0) { BRANCH_F (IR); } + break; + case 022: case 023: /* BGE */ + if (CC_XOR_NV (cc) == 0) { BRANCH_B (IR); } + break; + case 024: case 025: /* BLT */ + if (CC_XOR_NV (cc)) { BRANCH_F (IR); } + break; + case 026: case 027: /* BLT */ + if (CC_XOR_NV (cc)) { BRANCH_B (IR); } + break; + case 030: case 031: /* BGT */ + if (((cc & CC_Z) || CC_XOR_NV (cc)) == 0) { BRANCH_F (IR); } + break; + case 032: case 033: /* BGT */ + if (((cc & CC_Z) || CC_XOR_NV (cc)) == 0) { BRANCH_B (IR); } + break; + case 034: case 035: /* BLE */ + if ((cc & CC_Z) || CC_XOR_NV (cc)) { BRANCH_F (IR); } + break; + case 036: case 037: /* BLE */ + if ((cc & CC_Z) || CC_XOR_NV (cc)) { BRANCH_B (IR); } + break; + case 040: case 041: case 042: case 043: /* JSR */ + case 044: case 045: case 046: case 047: + if (dstreg) CMODE_FAULT (CMODE_ILLI); /* mode 0 illegal */ + else { + srcspec = srcspec & 07; /* get reg num */ + dst = GeteaW (dstspec); /* get dst addr */ + src = RdRegW (srcspec); /* get src reg */ + WrMemW (src, (R[6] - 2) & WMASK); /* -(sp) <- r */ + R[6] = (R[6] - 2) & WMASK; + if (srcspec != 7) WrRegW (PC, srcspec); /* r <- PC */ + CMODE_JUMP (dst); /* PC <- dst */ + } + break; /* end JSR */ + case 050: /* CLR */ + if (dstreg) WrRegW (0, dstspec); + else WrMemW (0, GeteaW (dstspec)); + cc = CC_Z; + break; + case 051: /* COM */ + if (dstreg) src = RdRegW (dstspec); + else src = RdMemMW (ea = GeteaW (dstspec)); + dst = src ^ WMASK; + if (dstreg) WrRegW (dst, dstspec); + else WrMemW (dst, ea); + CC_IIZZ_W (dst); + cc = cc | CC_C; + break; + case 052: /* INC */ + if (dstreg) src = RdRegW (dstspec); + else src = RdMemMW (ea = GeteaW (dstspec)); + dst = (src + 1) & WMASK; + if (dstreg) WrRegW (dst, dstspec); + else WrMemW (dst, ea); + CC_IIZP_W (dst); + if (dst == 0100000) cc = cc | CC_V; + break; + case 053: /* DEC */ + if (dstreg) src = RdRegW (dstspec); + else src = RdMemMW (ea = GeteaW (dstspec)); + dst = (src - 1) & WMASK; + if (dstreg) WrRegW (dst, dstspec); + else WrMemW (dst, ea); + CC_IIZP_W (dst); + if (dst == 077777) cc = cc | CC_V; + break; + case 054: /* NEG */ + if (dstreg) src = RdRegW (dstspec); + else src = RdMemMW (ea = GeteaW (dstspec)); + dst = (-src) & WMASK; + if (dstreg) WrRegW (dst, dstspec); + else WrMemW (dst, ea); + CC_IIZZ_W (dst); + if (dst == 0100000) cc = cc | CC_V; + if (dst) cc = cc | CC_C; + break; + case 055: /* ADC */ + if (dstreg) src = RdRegW (dstspec); + else src = RdMemMW (ea = GeteaW (dstspec)); + dst = (src + (cc & CC_C)) & WMASK; + if (dstreg) WrRegW (dst, dstspec); + else WrMemW (dst, ea); + CC_IIZZ_W (dst); + if ((src == 077777) && (dst == 0100000)) cc = cc | CC_V; + if ((src == 0177777) && (dst == 0)) cc = cc | CC_C; + break; + case 056: /* SBC */ + if (dstreg) src = RdRegW (dstspec); + else src = RdMemMW (ea = GeteaW (dstspec)); + dst = (src - (cc & CC_C)) & WMASK; + if (dstreg) WrRegW (dst, dstspec); + else WrMemW (dst, ea); + CC_IIZZ_W (dst); + if ((src == 0100000) && (dst == 077777)) cc = cc | CC_V; + if ((src == 0) && (dst == 0177777)) cc = cc | CC_C; + break; + case 057: /* TST */ + if (dstreg) src = RdRegW (dstspec); + else src = RdMemW (GeteaW (dstspec)); + CC_IIZZ_W (src); + break; + case 060: /* ROR */ + if (dstreg) src = RdRegW (dstspec); + else src = RdMemMW (ea = GeteaW (dstspec)); + dst = (src >> 1) | ((cc & CC_C)? WSIGN: 0); + if (dstreg) WrRegW (dst, dstspec); + else WrMemW (dst, ea); + CC_IIZZ_W (dst); + if (src & 1) cc = cc | CC_C; + if (CC_XOR_NC (cc)) cc = cc | CC_V; + break; + case 061: /* ROL */ + if (dstreg) src = RdRegW (dstspec); + else src = RdMemMW (ea = GeteaW (dstspec)); + dst = ((src << 1) | ((cc & CC_C)? 1: 0)) & WMASK; + if (dstreg) WrRegW (dst, dstspec); + else WrMemW (dst, ea); + CC_IIZZ_W (dst); + if (src & WSIGN) cc = cc | CC_C; + if (CC_XOR_NC (cc)) cc = cc | CC_V; + break; + case 062: /* ASR */ + if (dstreg) src = RdRegW (dstspec); + else src = RdMemMW (ea = GeteaW (dstspec)); + dst = (src & WSIGN) | (src >> 1); + if (dstreg) WrRegW (dst, dstspec); + else WrMemW (dst, ea); + CC_IIZZ_W (dst); + if (src & 1) cc = cc | CC_C; + if (CC_XOR_NC (cc)) cc = cc | CC_V; + break; + case 063: /* ASL */ + if (dstreg) src = RdRegW (dstspec); + else src = RdMemMW (ea = GeteaW (dstspec)); + dst = (src << 1) & WMASK; + if (dstreg) WrRegW (dst, dstspec); + else WrMemW (dst, ea); + CC_IIZZ_W (dst); + if (src & WSIGN) cc = cc | CC_C; + if (CC_XOR_NC (cc)) cc = cc | CC_V; + break; + case 065: /* MFPI */ + if (dstreg) dst = RdRegW (dstspec); /* "mov dst,-(sp)" */ + else dst = RdMemW (GeteaW (dstspec)); + WrMemW (dst, (R[6] - 2) & WMASK); + R[6] = (R[6] - 2) & WMASK; + CC_IIZP_W (dst); + break; + case 066: /* MTPI */ + dst = RdMemW (R[6] & WMASK); /* "mov (sp)+,dst" */ + R[6] = (R[6] + 2) & WMASK; + recq[recqptr++] = RQ_REC (AIN|RW, 6); + if (dstreg) WrRegW (dst, dstspec); + else WrMemW (dst, (GeteaW (dstspec) & WMASK)); + CC_IIZP_W (dst); + break; + default: /* undefined */ + CMODE_FAULT (CMODE_RSVI); + break; + } /* end switch SOPs */ + break; /* end case 000 */ - case 001: /* JMP */ - if (dstreg) CMODE_FAULT (CMODE_ILLI); /* mode 0 illegal */ - else { CMODE_JUMP (GeteaW (dstspec)); } - break; - case 002: /* 0002xx */ - if (IR < 000210) { /* RTS */ - dstspec = dstspec & 07; - if (dstspec != 7) { /* PC <- r */ - CMODE_JUMP (RdRegW (dstspec)); - } - dst = RdMemW (R[6]); /* t <- (sp)+ */ - R[6] = (R[6] + 2) & WMASK; - WrRegW (dst, dstspec); /* r <- t */ - break; } /* end if RTS */ - if (IR < 000240) { /* [210:237] */ - CMODE_FAULT (CMODE_RSVI); - break; - } - if (IR < 000260) cc = cc & ~(IR & CC_MASK); /* clear CC */ - else cc = cc | (IR & CC_MASK); /* set CC */ - break; - case 003: /* SWAB */ - if (dstreg) src = RdRegW (dstspec); - else src = RdMemMW (ea = GeteaW (dstspec)); - dst = ((src & BMASK) << 8) | ((src >> 8) & BMASK); - if (dstreg) WrRegW (dst, dstspec); - else WrMemW (dst, ea); - CC_IIZZ_B ((dst & BMASK)); - break; - -/* 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 ((cc & CC_Z) == 0) { BRANCH_F (IR); } - break; - case 012: case 013: /* BNE */ - if ((cc & CC_Z) == 0) { BRANCH_B (IR); } - break; - case 014: case 015: /* BEQ */ - if (cc & CC_Z) { BRANCH_F (IR); } - break; - case 016: case 017: /* BEQ */ - if (cc & CC_Z) { BRANCH_B (IR); } - break; - case 020: case 021: /* BGE */ - if (CC_XOR_NV (cc) == 0) { BRANCH_F (IR); } - break; - case 022: case 023: /* BGE */ - if (CC_XOR_NV (cc) == 0) { BRANCH_B (IR); } - break; - case 024: case 025: /* BLT */ - if (CC_XOR_NV (cc)) { BRANCH_F (IR); } - break; - case 026: case 027: /* BLT */ - if (CC_XOR_NV (cc)) { BRANCH_B (IR); } - break; - case 030: case 031: /* BGT */ - if (((cc & CC_Z) || CC_XOR_NV (cc)) == 0) { BRANCH_F (IR); } - break; - case 032: case 033: /* BGT */ - if (((cc & CC_Z) || CC_XOR_NV (cc)) == 0) { BRANCH_B (IR); } - break; - case 034: case 035: /* BLE */ - if ((cc & CC_Z) || CC_XOR_NV (cc)) { BRANCH_F (IR); } - break; - case 036: case 037: /* BLE */ - if ((cc & CC_Z) || CC_XOR_NV (cc)) { BRANCH_B (IR); } - break; - case 040: case 041: case 042: case 043: /* JSR */ - case 044: case 045: case 046: case 047: - if (dstreg) CMODE_FAULT (CMODE_ILLI); /* mode 0 illegal */ - else { - srcspec = srcspec & 07; /* get reg num */ - dst = GeteaW (dstspec); /* get dst addr */ - src = RdRegW (srcspec); /* get src reg */ - WrMemW (src, (R[6] - 2) & WMASK); /* -(sp) <- r */ - R[6] = (R[6] - 2) & WMASK; - if (srcspec != 7) WrRegW (PC, srcspec); /* r <- PC */ - CMODE_JUMP (dst); /* PC <- dst */ - } - break; /* end JSR */ - -/* Opcode 0: SOPs */ - - case 050: /* CLR */ - if (dstreg) WrRegW (0, dstspec); - else WrMemW (0, GeteaW (dstspec)); - cc = CC_Z; - break; - case 051: /* COM */ - if (dstreg) src = RdRegW (dstspec); - else src = RdMemMW (ea = GeteaW (dstspec)); - dst = src ^ WMASK; - if (dstreg) WrRegW (dst, dstspec); - else WrMemW (dst, ea); - CC_IIZZ_W (dst); - cc = cc | CC_C; - break; - case 052: /* INC */ - if (dstreg) src = RdRegW (dstspec); - else src = RdMemMW (ea = GeteaW (dstspec)); - dst = (src + 1) & WMASK; - if (dstreg) WrRegW (dst, dstspec); - else WrMemW (dst, ea); - CC_IIZP_W (dst); - if (dst == 0100000) cc = cc | CC_V; - break; - case 053: /* DEC */ - if (dstreg) src = RdRegW (dstspec); - else src = RdMemMW (ea = GeteaW (dstspec)); - dst = (src - 1) & WMASK; - if (dstreg) WrRegW (dst, dstspec); - else WrMemW (dst, ea); - CC_IIZP_W (dst); - if (dst == 077777) cc = cc | CC_V; - break; - case 054: /* NEG */ - if (dstreg) src = RdRegW (dstspec); - else src = RdMemMW (ea = GeteaW (dstspec)); - dst = (-src) & WMASK; - if (dstreg) WrRegW (dst, dstspec); - else WrMemW (dst, ea); - CC_IIZZ_W (dst); - if (dst == 0100000) cc = cc | CC_V; - if (dst) cc = cc | CC_C; - break; - case 055: /* ADC */ - if (dstreg) src = RdRegW (dstspec); - else src = RdMemMW (ea = GeteaW (dstspec)); - dst = (src + (cc & CC_C)) & WMASK; - if (dstreg) WrRegW (dst, dstspec); - else WrMemW (dst, ea); - CC_IIZZ_W (dst); - if ((src == 077777) && (dst == 0100000)) cc = cc | CC_V; - if ((src == 0177777) && (dst == 0)) cc = cc | CC_C; - break; - case 056: /* SBC */ - if (dstreg) src = RdRegW (dstspec); - else src = RdMemMW (ea = GeteaW (dstspec)); - dst = (src - (cc & CC_C)) & WMASK; - if (dstreg) WrRegW (dst, dstspec); - else WrMemW (dst, ea); - CC_IIZZ_W (dst); - if ((src == 0100000) && (dst == 077777)) cc = cc | CC_V; - if ((src == 0) && (dst == 0177777)) cc = cc | CC_C; - break; - case 057: /* TST */ - if (dstreg) src = RdRegW (dstspec); - else src = RdMemW (GeteaW (dstspec)); - CC_IIZZ_W (src); - break; - case 060: /* ROR */ - if (dstreg) src = RdRegW (dstspec); - else src = RdMemMW (ea = GeteaW (dstspec)); - dst = (src >> 1) | ((cc & CC_C)? WSIGN: 0); - if (dstreg) WrRegW (dst, dstspec); - else WrMemW (dst, ea); - CC_IIZZ_W (dst); - if (src & 1) cc = cc | CC_C; - if (CC_XOR_NC (cc)) cc = cc | CC_V; - break; - case 061: /* ROL */ - if (dstreg) src = RdRegW (dstspec); - else src = RdMemMW (ea = GeteaW (dstspec)); - dst = ((src << 1) | ((cc & CC_C)? 1: 0)) & WMASK; - if (dstreg) WrRegW (dst, dstspec); - else WrMemW (dst, ea); - CC_IIZZ_W (dst); - if (src & WSIGN) cc = cc | CC_C; - if (CC_XOR_NC (cc)) cc = cc | CC_V; - break; - case 062: /* ASR */ - if (dstreg) src = RdRegW (dstspec); - else src = RdMemMW (ea = GeteaW (dstspec)); - dst = (src & WSIGN) | (src >> 1); - if (dstreg) WrRegW (dst, dstspec); - else WrMemW (dst, ea); - CC_IIZZ_W (dst); - if (src & 1) cc = cc | CC_C; - if (CC_XOR_NC (cc)) cc = cc | CC_V; - break; - case 063: /* ASL */ - if (dstreg) src = RdRegW (dstspec); - else src = RdMemMW (ea = GeteaW (dstspec)); - dst = (src << 1) & WMASK; - if (dstreg) WrRegW (dst, dstspec); - else WrMemW (dst, ea); - CC_IIZZ_W (dst); - if (src & WSIGN) cc = cc | CC_C; - if (CC_XOR_NC (cc)) cc = cc | CC_V; - break; - case 065: /* MFPI */ - if (dstreg) dst = RdRegW (dstspec); /* "mov dst,-(sp)" */ - else dst = RdMemW (GeteaW (dstspec)); - WrMemW (dst, (R[6] - 2) & WMASK); - R[6] = (R[6] - 2) & WMASK; - CC_IIZP_W (dst); - break; - case 066: /* MTPI */ - dst = RdMemW (R[6] & WMASK); /* "mov (sp)+,dst" */ - R[6] = (R[6] + 2) & WMASK; - recq[recqptr++] = RQ_REC (AIN|RW, 6); - if (dstreg) WrRegW (dst, dstspec); - else WrMemW (dst, (GeteaW (dstspec) & WMASK)); - CC_IIZP_W (dst); - break; - default: /* undefined */ - CMODE_FAULT (CMODE_RSVI); - break; - } /* end switch SOPs */ - break; /* end case 000 */ - /* Opcodes 01 - 06: double operand word instructions Compatibility mode requires source address decode, source fetch, @@ -360,70 +353,75 @@ case 000: /* 00xxxx */ Cmp: v = [sign (src) != sign (src2)] and [sign (src2) = sign (result)] */ -case 001: /* MOV */ - if (srcreg) src = RdRegW (srcspec); - else src = RdMemW (GeteaW (srcspec)); - if (dstreg) WrRegW (src, dstspec); - else WrMemW (src, GeteaW (dstspec)); - CC_IIZP_W (src); - break; -case 002: /* CMP */ - if (srcreg) src = RdRegW (srcspec); - else src = RdMemW (GeteaW (srcspec)); - if (dstreg) src2 = RdRegW (dstspec); - else src2 = RdMemW (GeteaW (dstspec)); - dst = (src - src2) & WMASK; - CC_IIZZ_W (dst); - if (((src ^ src2) & (~src2 ^ dst)) & WSIGN) cc = cc | CC_V; - if (src < src2) cc = cc | CC_C; - break; -case 003: /* BIT */ - if (srcreg) src = RdRegW (srcspec); - else src = RdMemW (GeteaW (srcspec)); - if (dstreg) src2 = RdRegW (dstspec); - else src2 = RdMemW (GeteaW (dstspec)); - dst = src2 & src; - CC_IIZP_W (dst); - break; -case 004: /* BIC */ - if (srcreg) src = RdRegW (srcspec); - else src = RdMemW (GeteaW (srcspec)); - if (dstreg) src2 = RdRegW (dstspec); - else src2 = RdMemMW (ea = GeteaW (dstspec)); - dst = src2 & ~src; - if (dstreg) WrRegW (dst, dstspec); - else WrMemW (dst, ea); - CC_IIZP_W (dst); - break; -case 005: /* BIS */ - if (srcreg) src = RdRegW (srcspec); - else src = RdMemW (GeteaW (srcspec)); - if (dstreg) src2 = RdRegW (dstspec); - else src2 = RdMemMW (ea = GeteaW (dstspec)); - dst = src2 | src; - if (dstreg) WrRegW (dst, dstspec); - else WrMemW (dst, ea); - CC_IIZP_W (dst); - break; -case 006: /* ADD */ - if (srcreg) src = RdRegW (srcspec); - else src = RdMemW (GeteaW (srcspec)); - if (dstreg) src2 = RdRegW (dstspec); - else src2 = RdMemMW (ea = GeteaW (dstspec)); - dst = (src2 + src) & WMASK; - if (dstreg) WrRegW (dst, dstspec); - else WrMemW (dst, ea); - CC_ADD_W (dst, src, src2); - break; - + case 001: /* MOV */ + if (srcreg) src = RdRegW (srcspec); + else src = RdMemW (GeteaW (srcspec)); + if (dstreg) WrRegW (src, dstspec); + else WrMemW (src, GeteaW (dstspec)); + CC_IIZP_W (src); + break; + + case 002: /* CMP */ + if (srcreg) src = RdRegW (srcspec); + else src = RdMemW (GeteaW (srcspec)); + if (dstreg) src2 = RdRegW (dstspec); + else src2 = RdMemW (GeteaW (dstspec)); + dst = (src - src2) & WMASK; + CC_IIZZ_W (dst); + if (((src ^ src2) & (~src2 ^ dst)) & WSIGN) cc = cc | CC_V; + if (src < src2) cc = cc | CC_C; + break; + + case 003: /* BIT */ + if (srcreg) src = RdRegW (srcspec); + else src = RdMemW (GeteaW (srcspec)); + if (dstreg) src2 = RdRegW (dstspec); + else src2 = RdMemW (GeteaW (dstspec)); + dst = src2 & src; + CC_IIZP_W (dst); + break; + + case 004: /* BIC */ + if (srcreg) src = RdRegW (srcspec); + else src = RdMemW (GeteaW (srcspec)); + if (dstreg) src2 = RdRegW (dstspec); + else src2 = RdMemMW (ea = GeteaW (dstspec)); + dst = src2 & ~src; + if (dstreg) WrRegW (dst, dstspec); + else WrMemW (dst, ea); + CC_IIZP_W (dst); + break; + + case 005: /* BIS */ + if (srcreg) src = RdRegW (srcspec); + else src = RdMemW (GeteaW (srcspec)); + if (dstreg) src2 = RdRegW (dstspec); + else src2 = RdMemMW (ea = GeteaW (dstspec)); + dst = src2 | src; + if (dstreg) WrRegW (dst, dstspec); + else WrMemW (dst, ea); + CC_IIZP_W (dst); + break; + + case 006: /* ADD */ + if (srcreg) src = RdRegW (srcspec); + else src = RdMemW (GeteaW (srcspec)); + if (dstreg) src2 = RdRegW (dstspec); + else src2 = RdMemMW (ea = GeteaW (dstspec)); + dst = (src2 + src) & WMASK; + if (dstreg) WrRegW (dst, dstspec); + else WrMemW (dst, ea); + CC_ADD_W (dst, src, src2); + break; + /* Opcode 07: EIS, FIS (not implemented), CIS Notes: - 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. + 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). @@ -432,518 +430,532 @@ case 006: /* ADD */ extends, then the shift and conditional or does sign extension. */ -case 007: /* EIS */ - srcspec = srcspec & 07; /* get src reg */ - switch ((IR >> 9) & 07) { /* decode IR<11:9> */ + case 007: /* EIS */ + srcspec = srcspec & 07; /* get src reg */ + switch ((IR >> 9) & 07) { /* decode IR<11:9> */ - case 0: /* MUL */ - if (dstreg) src2 = RdRegW (dstspec); /* get src2 */ - else src2 = RdMemW (GeteaW (dstspec)); - src = RdRegW (srcspec); /* get src */ - if (src2 & WSIGN) src2 = src2 | ~WMASK; /* sext src, src2 */ - if (src & WSIGN) src = src | ~WMASK; - dst = src * src2; /* multiply */ - WrRegW ((dst >> 16) & WMASK, srcspec); /* high 16b */ - WrRegW (dst & WMASK, srcspec | 1); /* low 16b */ - CC_IIZZ_L (dst & LMASK); - if ((dst > 077777) || (dst < -0100000)) cc = cc | CC_C; - break; + case 0: /* MUL */ + if (dstreg) src2 = RdRegW (dstspec); /* get src2 */ + else src2 = RdMemW (GeteaW (dstspec)); + src = RdRegW (srcspec); /* get src */ + if (src2 & WSIGN) src2 = src2 | ~WMASK; /* sext src, src2 */ + if (src & WSIGN) src = src | ~WMASK; + dst = src * src2; /* multiply */ + WrRegW ((dst >> 16) & WMASK, srcspec); /* high 16b */ + WrRegW (dst & WMASK, srcspec | 1); /* low 16b */ + CC_IIZZ_L (dst & LMASK); + if ((dst > 077777) || (dst < -0100000)) cc = cc | CC_C; + break; - case 1: /* DIV */ - if (dstreg) src2 = RdRegW (dstspec); /* get src2 */ - else src2 = RdMemW (GeteaW (dstspec)); - t = RdRegW (srcspec); - src = (((uint32) t) << 16) | RdRegW (srcspec | 1); - if (src2 == 0) { /* div by 0? */ - cc = CC_V | CC_C; /* set cc's */ - break; /* done */ - } - if ((src == LSIGN) && (src2 == WMASK)) { /* -2^31 / -1? */ - cc = CC_V; /* overflow */ - break; /* done */ - } - if (src2 & WSIGN) src2 = src2 | ~WMASK; /* sext src, src2 */ - if (t & WSIGN) src = src | ~LMASK; - dst = src / src2; /* divide */ - if ((dst > 077777) || (dst < -0100000)) { /* out of range? */ - cc = CC_V; /* overflow */ - break; - } - CC_IIZZ_W (dst & WMASK); /* set cc's */ - WrRegW (dst & WMASK, srcspec); /* quotient */ - WrRegW ((src - (src2 * dst)) & WMASK, srcspec | 1); - break; - -/* Opcode 7: EIS, continued */ + case 1: /* DIV */ + if (dstreg) src2 = RdRegW (dstspec); /* get src2 */ + else src2 = RdMemW (GeteaW (dstspec)); + t = RdRegW (srcspec); + src = (((uint32) t) << 16) | RdRegW (srcspec | 1); + if (src2 == 0) { /* div by 0? */ + cc = CC_V | CC_C; /* set cc's */ + break; /* done */ + } + if ((src == LSIGN) && (src2 == WMASK)) { /* -2^31 / -1? */ + cc = CC_V; /* overflow */ + break; /* done */ + } + if (src2 & WSIGN) src2 = src2 | ~WMASK; /* sext src, src2 */ + if (t & WSIGN) src = src | ~LMASK; + dst = src / src2; /* divide */ + if ((dst > 077777) || (dst < -0100000)) { /* out of range? */ + cc = CC_V; /* overflow */ + break; + } + CC_IIZZ_W (dst & WMASK); /* set cc's */ + WrRegW (dst & WMASK, srcspec); /* quotient */ + WrRegW ((src - (src2 * dst)) & WMASK, srcspec | 1); + break; - case 2: /* ASH */ - if (dstreg) src2 = RdRegW (dstspec); /* get src2 */ - else src2 = RdMemW (GeteaW (dstspec)); - src2 = src2 & 077; - src = RdRegW (srcspec); /* get src */ - if (sign = ((src & WSIGN)? 1: 0)) src = src | ~WMASK; - if (src2 == 0) { /* [0] */ - dst = src; /* result */ - oc = 0; /* last bit out */ - } - else if (src2 <= 15) { /* [1,15] */ - dst = src << src2; - i = (src >> (16 - src2)) & WMASK; - oc = (i & 1)? CC_C: 0; - if ((dst & WSIGN)? (i != WMASK): (i != 0)) oc = oc | CC_V; - } - else if (src2 <= 31) { /* [16,31] */ - dst = 0; - oc = ((src << (src2 - 16)) & 1)? CC_C: 0; - if (src) oc = oc | CC_V; - } - else if (src2 == 32) { /* [32] = -32 */ - dst = -sign; - oc = sign? CC_C: 0; - } - else { /* [33,63] = -31,-1 */ - dst = (src >> (64 - src2)) | (-sign << (src2 - 32)); - oc = ((src >> (63 - src2)) & 1)? CC_C: 0; - } - WrRegW (dst = dst & WMASK, srcspec); /* result */ - CC_IIZZ_W (dst); - cc = cc | oc; - break; + case 2: /* ASH */ + if (dstreg) src2 = RdRegW (dstspec); /* get src2 */ + else src2 = RdMemW (GeteaW (dstspec)); + src2 = src2 & 077; + src = RdRegW (srcspec); /* get src */ + if (sign = ((src & WSIGN)? 1: 0)) src = src | ~WMASK; + if (src2 == 0) { /* [0] */ + dst = src; /* result */ + oc = 0; /* last bit out */ + } + else if (src2 <= 15) { /* [1,15] */ + dst = src << src2; + i = (src >> (16 - src2)) & WMASK; + oc = (i & 1)? CC_C: 0; + if ((dst & WSIGN)? (i != WMASK): (i != 0)) oc = oc | CC_V; + } + else if (src2 <= 31) { /* [16,31] */ + dst = 0; + oc = ((src << (src2 - 16)) & 1)? CC_C: 0; + if (src) oc = oc | CC_V; + } + else if (src2 == 32) { /* [32] = -32 */ + dst = -sign; + oc = sign? CC_C: 0; + } + else { /* [33,63] = -31,-1 */ + dst = (src >> (64 - src2)) | (-sign << (src2 - 32)); + oc = ((src >> (63 - src2)) & 1)? CC_C: 0; + } + WrRegW (dst = dst & WMASK, srcspec); /* result */ + CC_IIZZ_W (dst); + cc = cc | oc; + break; - case 3: /* ASHC */ - if (dstreg) src2 = RdRegW (dstspec); /* get src2 */ - else src2 = RdMemW (GeteaW (dstspec)); - src2 = src2 & 077; - t = RdRegW (srcspec); - src = (((uint32) t) << 16) | RdRegW (srcspec | 1); - sign = (t & WSIGN)? 1: 0; /* get src sign */ - if (src2 == 0) { /* [0] */ - dst = src; /* result */ - oc = 0; /* last bit out */ - } - else if (src2 <= 31) { /* [1,31] */ - dst = ((uint32) src) << src2; - i = ((src >> (32 - src2)) | (-sign << src2)) & LMASK; - oc = (i & 1)? CC_C: 0; - if ((dst & LSIGN)? (i != LMASK): (i != 0)) oc = oc | CC_V; - } - else if (src2 == 32) { /* [32] = -32 */ - dst = -sign; - oc = sign? CC_C: 0; - } - else { /* [33,63] = -31,-1 */ - dst = (src >> (64 - src2)) | (-sign << (src2 - 32)); - oc = ((src >> (63 - src2)) & 1)? CC_C: 0; - } - WrRegW ((dst >> 16) & WMASK, srcspec); /* high result */ - WrRegW (dst & WMASK, srcspec | 1); /* low result */ - CC_IIZZ_L (dst & LMASK); - cc = cc | oc; - break; - -/* Opcode 7: EIS, continued */ + case 3: /* ASHC */ + if (dstreg) src2 = RdRegW (dstspec); /* get src2 */ + else src2 = RdMemW (GeteaW (dstspec)); + src2 = src2 & 077; + t = RdRegW (srcspec); + src = (((uint32) t) << 16) | RdRegW (srcspec | 1); + sign = (t & WSIGN)? 1: 0; /* get src sign */ + if (src2 == 0) { /* [0] */ + dst = src; /* result */ + oc = 0; /* last bit out */ + } + else if (src2 <= 31) { /* [1,31] */ + dst = ((uint32) src) << src2; + i = ((src >> (32 - src2)) | (-sign << src2)) & LMASK; + oc = (i & 1)? CC_C: 0; + if ((dst & LSIGN)? (i != LMASK): (i != 0)) oc = oc | CC_V; + } + else if (src2 == 32) { /* [32] = -32 */ + dst = -sign; + oc = sign? CC_C: 0; + } + else { /* [33,63] = -31,-1 */ + dst = (src >> (64 - src2)) | (-sign << (src2 - 32)); + oc = ((src >> (63 - src2)) & 1)? CC_C: 0; + } + WrRegW ((dst >> 16) & WMASK, srcspec); /* high result */ + WrRegW (dst & WMASK, srcspec | 1); /* low result */ + CC_IIZZ_L (dst & LMASK); + cc = cc | oc; + break; - case 4: /* XOR */ - if (dstreg) src2 = RdRegW (dstspec); /* get dst */ - else src2 = RdMemMW (ea = GeteaW (dstspec)); - src = RdRegW (srcspec); /* get src */ - dst = src2 ^ src; - if (dstreg) WrRegW (dst, dstspec); /* result */ - else WrMemW (dst, ea); - CC_IIZP_W (dst); - break; + case 4: /* XOR */ + if (dstreg) src2 = RdRegW (dstspec); /* get dst */ + else src2 = RdMemMW (ea = GeteaW (dstspec)); + src = RdRegW (srcspec); /* get src */ + dst = src2 ^ src; + if (dstreg) WrRegW (dst, dstspec); /* result */ + else WrMemW (dst, ea); + CC_IIZP_W (dst); + break; - case 7: /* SOB */ - dst = (RdRegW (srcspec) - 1) & WMASK; /* decr reg */ - WrRegW (dst, srcspec); /* result */ - if (dst != 0) { /* br if zero */ - CMODE_JUMP ((PC - dstspec - dstspec) & WMASK); - } - break; + case 7: /* SOB */ + dst = (RdRegW (srcspec) - 1) & WMASK; /* decr reg */ + WrRegW (dst, srcspec); /* result */ + if (dst != 0) { /* br if zero */ + CMODE_JUMP ((PC - dstspec - dstspec) & WMASK); + } + break; + + default: + CMODE_FAULT (CMODE_RSVI); /* end switch EIS */ + } + break; /* end case 007 */ - default: - CMODE_FAULT (CMODE_RSVI); /* 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 ((cc & CC_N) == 0) { BRANCH_F (IR); } - break; - case 002: case 003: /* BPL */ - if ((cc & CC_N) == 0) { BRANCH_B (IR); } - break; - case 004: case 005: /* BMI */ - if (cc & CC_N) { BRANCH_F (IR); } - break; - case 006: case 007: /* BMI */ - if (cc & CC_N) { BRANCH_B (IR); } - break; - case 010: case 011: /* BHI */ - if ((cc & (CC_C | CC_Z)) == 0) { BRANCH_F (IR); } - break; - case 012: case 013: /* BHI */ - if ((cc & (CC_C | CC_Z)) == 0) { BRANCH_B (IR); } - break; - case 014: case 015: /* BLOS */ - if (cc & (CC_C | CC_Z)) { BRANCH_F (IR); } - break; - case 016: case 017: /* BLOS */ - if (cc & (CC_C | CC_Z)) { BRANCH_B (IR); } - break; - case 020: case 021: /* BVC */ - if ((cc & CC_V) == 0) { BRANCH_F (IR); } - break; - case 022: case 023: /* BVC */ - if ((cc & CC_V) == 0) { BRANCH_B (IR); } - break; - case 024: case 025: /* BVS */ - if (cc & CC_V) { BRANCH_F (IR); } - break; - case 026: case 027: /* BVS */ - if (cc & CC_V) { BRANCH_B (IR); } - break; - case 030: case 031: /* BCC */ - if ((cc & CC_C) == 0) { BRANCH_F (IR); } - break; - case 032: case 033: /* BCC */ - if ((cc & CC_C) == 0) { BRANCH_B (IR); } - break; - case 034: case 035: /* BCS */ - if (cc & CC_C) { BRANCH_F (IR); } - break; - case 036: case 037: /* BCS */ - if (cc & CC_C) { BRANCH_B (IR); } - break; - case 040: case 041: case 042: case 043: /* EMT */ - CMODE_FAULT (CMODE_EMT); - break; - case 044: case 045: case 046: case 047: /* TRAP */ - CMODE_FAULT (CMODE_TRAP); - break; - -/* Opcode 10, continued: SOPs */ + case 010: + switch ((IR >> 6) & 077) { /* decode IR<11:6> */ + case 000: case 001: /* BPL */ + if ((cc & CC_N) == 0) { BRANCH_F (IR); } + break; + case 002: case 003: /* BPL */ + if ((cc & CC_N) == 0) { BRANCH_B (IR); } + break; + case 004: case 005: /* BMI */ + if (cc & CC_N) { BRANCH_F (IR); } + break; + case 006: case 007: /* BMI */ + if (cc & CC_N) { BRANCH_B (IR); } + break; + case 010: case 011: /* BHI */ + if ((cc & (CC_C | CC_Z)) == 0) { BRANCH_F (IR); } + break; + case 012: case 013: /* BHI */ + if ((cc & (CC_C | CC_Z)) == 0) { BRANCH_B (IR); } + break; + case 014: case 015: /* BLOS */ + if (cc & (CC_C | CC_Z)) { BRANCH_F (IR); } + break; + case 016: case 017: /* BLOS */ + if (cc & (CC_C | CC_Z)) { BRANCH_B (IR); } + break; + case 020: case 021: /* BVC */ + if ((cc & CC_V) == 0) { BRANCH_F (IR); } + break; + case 022: case 023: /* BVC */ + if ((cc & CC_V) == 0) { BRANCH_B (IR); } + break; + case 024: case 025: /* BVS */ + if (cc & CC_V) { BRANCH_F (IR); } + break; + case 026: case 027: /* BVS */ + if (cc & CC_V) { BRANCH_B (IR); } + break; + case 030: case 031: /* BCC */ + if ((cc & CC_C) == 0) { BRANCH_F (IR); } + break; + case 032: case 033: /* BCC */ + if ((cc & CC_C) == 0) { BRANCH_B (IR); } + break; + case 034: case 035: /* BCS */ + if (cc & CC_C) { BRANCH_F (IR); } + break; + case 036: case 037: /* BCS */ + if (cc & CC_C) { BRANCH_B (IR); } + break; + case 040: case 041: case 042: case 043: /* EMT */ + CMODE_FAULT (CMODE_EMT); + break; + case 044: case 045: case 046: case 047: /* TRAP */ + CMODE_FAULT (CMODE_TRAP); + break; + case 050: /* CLRB */ + if (dstreg) WrRegB (0, dstspec); + else WrMemB (0, GeteaB (dstspec)); + cc = CC_Z; + break; + case 051: /* COMB */ + if (dstreg) src = RdRegB (dstspec); + else src = RdMemMB (ea = GeteaB (dstspec)); + dst = src ^ BMASK; + if (dstreg) WrRegB (dst, dstspec); + else WrMemB (dst, ea); + CC_IIZZ_B (dst); + cc = cc | CC_C; + break; + case 052: /* INCB */ + if (dstreg) src = RdRegB (dstspec); + else src = RdMemMB (ea = GeteaB (dstspec)); + dst = (src + 1) & BMASK; + if (dstreg) WrRegB (dst, dstspec); + else WrMemB (dst, ea); + CC_IIZP_B (dst); + if (dst == 0200) cc = cc | CC_V; + break; + case 053: /* DECB */ + if (dstreg) src = RdRegB (dstspec); + else src = RdMemMB (ea = GeteaB (dstspec)); + dst = (src - 1) & BMASK; + if (dstreg) WrRegB (dst, dstspec); + else WrMemB (dst, ea); + CC_IIZP_B (dst); + if (dst == 0177) cc = cc | CC_V; + break; + case 054: /* NEGB */ + if (dstreg) src = RdRegB (dstspec); + else src = RdMemMB (ea = GeteaB (dstspec)); + dst = (-src) & BMASK; + if (dstreg) WrRegB (dst, dstspec); + else WrMemB (dst, ea); + CC_IIZZ_B (dst); + if (dst == 0200) cc = cc | CC_V; + if (dst) cc = cc | CC_C; + break; + case 055: /* ADCB */ + if (dstreg) src = RdRegB (dstspec); + else src = RdMemMB (ea = GeteaB (dstspec)); + dst = (src + (cc & CC_C)) & BMASK; + if (dstreg) WrRegB (dst, dstspec); + else WrMemB (dst, ea); + CC_IIZZ_B (dst); + if ((src == 0177) && (dst == 0200)) cc = cc | CC_V; + if ((src == 0377) && (dst == 0)) cc = cc | CC_C; + break; + case 056: /* SBCB */ + if (dstreg) src = RdRegB (dstspec); + else src = RdMemMB (ea = GeteaB (dstspec)); + dst = (src - (cc & CC_C)) & BMASK; + if (dstreg) WrRegB (dst, dstspec); + else WrMemB (dst, ea); + CC_IIZZ_B (dst); + if ((src == 0200) && (dst == 0177)) cc = cc | CC_V; + if ((src == 0) && (dst == 0377)) cc = cc | CC_C; + break; + case 057: /* TSTB */ + if (dstreg) src = RdRegB (dstspec); + else src = RdMemB (GeteaB (dstspec)); + CC_IIZZ_B (src); + break; + case 060: /* RORB */ + if (dstreg) src = RdRegB (dstspec); + else src = RdMemMB (ea = GeteaB (dstspec)); + dst = (src >> 1) | ((cc & CC_C)? BSIGN: 0); + if (dstreg) WrRegB (dst, dstspec); + else WrMemB (dst, ea); + CC_IIZZ_B (dst); + if (src & 1) cc = cc | CC_C; + if (CC_XOR_NC (cc)) cc = cc | CC_V; + break; + case 061: /* ROLB */ + if (dstreg) src = RdRegB (dstspec); + else src = RdMemMB (ea = GeteaB (dstspec)); + dst = ((src << 1) | ((cc & CC_C)? 1: 0)) & BMASK; + if (dstreg) WrRegB (dst, dstspec); + else WrMemB (dst, ea); + CC_IIZZ_B (dst); + if (src & BSIGN) cc = cc | CC_C; + if (CC_XOR_NC (cc)) cc = cc | CC_V; + break; + case 062: /* ASRB */ + if (dstreg) src = RdRegB (dstspec); + else src = RdMemMB (ea = GeteaB (dstspec)); + dst = (src >> 1) | (src & BSIGN); + if (dstreg) WrRegB (dst, dstspec); + else WrMemB (dst, ea); + CC_IIZZ_B (dst); + if (src & 1) cc = cc | CC_C; + if (CC_XOR_NC (cc)) cc = cc | CC_V; + break; + case 063: /* ASLB */ + if (dstreg) src = RdRegB (dstspec); + else src = RdMemMB (ea = GeteaB (dstspec)); + dst = (src << 1) & BMASK; + if (dstreg) WrRegB (dst, dstspec); + else WrMemB (dst, ea); + CC_IIZZ_B (dst); + if (src & BSIGN) cc = cc | CC_C; + if (CC_XOR_NC (cc)) cc = cc | CC_V; + break; + case 065: /* MFPD */ + if (dstreg) dst = RdRegW (dstspec); /* "mov dst,-(sp)" */ + else dst = RdMemW (GeteaW (dstspec)); + WrMemW (dst, (R[6] - 2) & WMASK); + R[6] = (R[6] - 2) & WMASK; + CC_IIZP_W (dst); + break; + case 066: /* MTPD */ + dst = RdMemW (R[6] & WMASK); /* "mov (sp)+,dst" */ + R[6] = (R[6] + 2) & WMASK; + recq[recqptr++] = RQ_REC (AIN|RW, 6); + if (dstreg) WrRegW (dst, dstspec); + else WrMemW (dst, (GeteaW (dstspec) & WMASK)); + CC_IIZP_W (dst); + break; + default: + CMODE_FAULT (CMODE_RSVI); + break; } /* end switch SOPs */ + break; /* end case 010 */ - case 050: /* CLRB */ - if (dstreg) WrRegB (0, dstspec); - else WrMemB (0, GeteaB (dstspec)); - cc = CC_Z; - break; - case 051: /* COMB */ - if (dstreg) src = RdRegB (dstspec); - else src = RdMemMB (ea = GeteaB (dstspec)); - dst = src ^ BMASK; - if (dstreg) WrRegB (dst, dstspec); - else WrMemB (dst, ea); - CC_IIZZ_B (dst); - cc = cc | CC_C; - break; - case 052: /* INCB */ - if (dstreg) src = RdRegB (dstspec); - else src = RdMemMB (ea = GeteaB (dstspec)); - dst = (src + 1) & BMASK; - if (dstreg) WrRegB (dst, dstspec); - else WrMemB (dst, ea); - CC_IIZP_B (dst); - if (dst == 0200) cc = cc | CC_V; - break; - case 053: /* DECB */ - if (dstreg) src = RdRegB (dstspec); - else src = RdMemMB (ea = GeteaB (dstspec)); - dst = (src - 1) & BMASK; - if (dstreg) WrRegB (dst, dstspec); - else WrMemB (dst, ea); - CC_IIZP_B (dst); - if (dst == 0177) cc = cc | CC_V; - break; - case 054: /* NEGB */ - if (dstreg) src = RdRegB (dstspec); - else src = RdMemMB (ea = GeteaB (dstspec)); - dst = (-src) & BMASK; - if (dstreg) WrRegB (dst, dstspec); - else WrMemB (dst, ea); - CC_IIZZ_B (dst); - if (dst == 0200) cc = cc | CC_V; - if (dst) cc = cc | CC_C; - break; - case 055: /* ADCB */ - if (dstreg) src = RdRegB (dstspec); - else src = RdMemMB (ea = GeteaB (dstspec)); - dst = (src + (cc & CC_C)) & BMASK; - if (dstreg) WrRegB (dst, dstspec); - else WrMemB (dst, ea); - CC_IIZZ_B (dst); - if ((src == 0177) && (dst == 0200)) cc = cc | CC_V; - if ((src == 0377) && (dst == 0)) cc = cc | CC_C; - break; - case 056: /* SBCB */ - if (dstreg) src = RdRegB (dstspec); - else src = RdMemMB (ea = GeteaB (dstspec)); - dst = (src - (cc & CC_C)) & BMASK; - if (dstreg) WrRegB (dst, dstspec); - else WrMemB (dst, ea); - CC_IIZZ_B (dst); - if ((src == 0200) && (dst == 0177)) cc = cc | CC_V; - if ((src == 0) && (dst == 0377)) cc = cc | CC_C; - break; - case 057: /* TSTB */ - if (dstreg) src = RdRegB (dstspec); - else src = RdMemB (GeteaB (dstspec)); - CC_IIZZ_B (src); - break; - case 060: /* RORB */ - if (dstreg) src = RdRegB (dstspec); - else src = RdMemMB (ea = GeteaB (dstspec)); - dst = (src >> 1) | ((cc & CC_C)? BSIGN: 0); - if (dstreg) WrRegB (dst, dstspec); - else WrMemB (dst, ea); - CC_IIZZ_B (dst); - if (src & 1) cc = cc | CC_C; - if (CC_XOR_NC (cc)) cc = cc | CC_V; - break; - case 061: /* ROLB */ - if (dstreg) src = RdRegB (dstspec); - else src = RdMemMB (ea = GeteaB (dstspec)); - dst = ((src << 1) | ((cc & CC_C)? 1: 0)) & BMASK; - if (dstreg) WrRegB (dst, dstspec); - else WrMemB (dst, ea); - CC_IIZZ_B (dst); - if (src & BSIGN) cc = cc | CC_C; - if (CC_XOR_NC (cc)) cc = cc | CC_V; - break; - case 062: /* ASRB */ - if (dstreg) src = RdRegB (dstspec); - else src = RdMemMB (ea = GeteaB (dstspec)); - dst = (src >> 1) | (src & BSIGN); - if (dstreg) WrRegB (dst, dstspec); - else WrMemB (dst, ea); - CC_IIZZ_B (dst); - if (src & 1) cc = cc | CC_C; - if (CC_XOR_NC (cc)) cc = cc | CC_V; - break; - case 063: /* ASLB */ - if (dstreg) src = RdRegB (dstspec); - else src = RdMemMB (ea = GeteaB (dstspec)); - dst = (src << 1) & BMASK; - if (dstreg) WrRegB (dst, dstspec); - else WrMemB (dst, ea); - CC_IIZZ_B (dst); - if (src & BSIGN) cc = cc | CC_C; - if (CC_XOR_NC (cc)) cc = cc | CC_V; - break; - case 065: /* MFPD */ - if (dstreg) dst = RdRegW (dstspec); /* "mov dst,-(sp)" */ - else dst = RdMemW (GeteaW (dstspec)); - WrMemW (dst, (R[6] - 2) & WMASK); - R[6] = (R[6] - 2) & WMASK; - CC_IIZP_W (dst); - break; - case 066: /* MTPD */ - dst = RdMemW (R[6] & WMASK); /* "mov (sp)+,dst" */ - R[6] = (R[6] + 2) & WMASK; - recq[recqptr++] = RQ_REC (AIN|RW, 6); - if (dstreg) WrRegW (dst, dstspec); - else WrMemW (dst, (GeteaW (dstspec) & WMASK)); - CC_IIZP_W (dst); - break; - default: - CMODE_FAULT (CMODE_RSVI); - 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) src = RdRegB (srcspec); - else src = RdMemB (GeteaB (srcspec)); - if (dstreg) WrRegW ((src & BSIGN)? (0xFF00 | src): src, dstspec); - else WrMemB (src, GeteaB (dstspec)); - CC_IIZP_B (src); - break; -case 012: /* CMPB */ - if (srcreg) src = RdRegB (srcspec); - else src = RdMemB (GeteaB (srcspec)); - if (dstreg) src2 = RdRegB (dstspec); - else src2 = RdMemB (GeteaB (dstspec)); - dst = (src - src2) & BMASK; - CC_IIZZ_B (dst); - if (((src ^ src2) & (~src2 ^ dst)) & BSIGN) cc = cc | CC_V; - if (src < src2) cc = cc | CC_C; - break; -case 013: /* BITB */ - if (srcreg) src = RdRegB (srcspec); - else src = RdMemB (GeteaB (srcspec)); - if (dstreg) src2 = RdRegB (dstspec); - else src2 = RdMemB (GeteaB (dstspec)); - dst = src2 & src; - CC_IIZP_B (dst); - break; -case 014: /* BICB */ - if (srcreg) src = RdRegB (srcspec); - else src = RdMemB (GeteaB (srcspec)); - if (dstreg) src2 = RdRegB (dstspec); - else src2 = RdMemMB (ea = GeteaB (dstspec)); - dst = src2 & ~src; - if (dstreg) WrRegB (dst, dstspec); - else WrMemB (dst, ea); - CC_IIZP_B (dst); - break; -case 015: /* BISB */ - if (srcreg) src = RdRegB (srcspec); - else src = RdMemB (GeteaB (srcspec)); - if (dstreg) src2 = RdRegB (dstspec); - else src2 = RdMemMB (ea = GeteaB (dstspec)); - dst = src2 | src; - if (dstreg) WrRegB (dst, dstspec); - else WrMemB (dst, ea); - CC_IIZP_B (dst); - break; -case 016: /* SUB */ - if (srcreg) src = RdRegW (srcspec); - else src = RdMemW (GeteaW (srcspec)); - if (dstreg) src2 = RdRegW (dstspec); - else src2 = RdMemMW (ea = GeteaW (dstspec)); - dst = (src2 - src) & WMASK; - if (dstreg) WrRegW (dst, dstspec); - else WrMemW (dst, ea); - CC_IIZZ_W (dst); - if (((src ^ src2) & (~src ^ dst)) & WSIGN) cc = cc | CC_V; - if (src2 < src) cc = cc | CC_C; - break; -default: - CMODE_FAULT (CMODE_RSVI); - break; - } /* end switch op */ + case 011: /* MOVB */ + if (srcreg) src = RdRegB (srcspec); + else src = RdMemB (GeteaB (srcspec)); + if (dstreg) WrRegW ((src & BSIGN)? (0xFF00 | src): src, dstspec); + else WrMemB (src, GeteaB (dstspec)); + CC_IIZP_B (src); + break; + + case 012: /* CMPB */ + if (srcreg) src = RdRegB (srcspec); + else src = RdMemB (GeteaB (srcspec)); + if (dstreg) src2 = RdRegB (dstspec); + else src2 = RdMemB (GeteaB (dstspec)); + dst = (src - src2) & BMASK; + CC_IIZZ_B (dst); + if (((src ^ src2) & (~src2 ^ dst)) & BSIGN) cc = cc | CC_V; + if (src < src2) cc = cc | CC_C; + break; + + case 013: /* BITB */ + if (srcreg) src = RdRegB (srcspec); + else src = RdMemB (GeteaB (srcspec)); + if (dstreg) src2 = RdRegB (dstspec); + else src2 = RdMemB (GeteaB (dstspec)); + dst = src2 & src; + CC_IIZP_B (dst); + break; + + case 014: /* BICB */ + if (srcreg) src = RdRegB (srcspec); + else src = RdMemB (GeteaB (srcspec)); + if (dstreg) src2 = RdRegB (dstspec); + else src2 = RdMemMB (ea = GeteaB (dstspec)); + dst = src2 & ~src; + if (dstreg) WrRegB (dst, dstspec); + else WrMemB (dst, ea); + CC_IIZP_B (dst); + break; + + case 015: /* BISB */ + if (srcreg) src = RdRegB (srcspec); + else src = RdMemB (GeteaB (srcspec)); + if (dstreg) src2 = RdRegB (dstspec); + else src2 = RdMemMB (ea = GeteaB (dstspec)); + dst = src2 | src; + if (dstreg) WrRegB (dst, dstspec); + else WrMemB (dst, ea); + CC_IIZP_B (dst); + break; + + case 016: /* SUB */ + if (srcreg) src = RdRegW (srcspec); + else src = RdMemW (GeteaW (srcspec)); + if (dstreg) src2 = RdRegW (dstspec); + else src2 = RdMemMW (ea = GeteaW (dstspec)); + dst = (src2 - src) & WMASK; + if (dstreg) WrRegW (dst, dstspec); + else WrMemW (dst, ea); + CC_IIZZ_W (dst); + if (((src ^ src2) & (~src ^ dst)) & WSIGN) cc = cc | CC_V; + if (src2 < src) cc = cc | CC_C; + break; + + default: + CMODE_FAULT (CMODE_RSVI); + break; + } /* end switch op */ + return cc; } - + /* Effective address calculations Inputs: - spec = specifier <5:0> + spec = specifier <5:0> Outputs: - ea = effective address + ea = effective address */ int32 GeteaW (int32 spec) { int32 adr, reg; -reg = spec & 07; /* register number */ -switch (spec >> 3) { /* decode spec<5:3> */ -default: /* can't get here */ -case 1: /* (R) */ - if (reg == 7) return (PC & WMASK); - else return (R[reg] & WMASK); -case 2: /* (R)+ */ - if (reg == 7) PC = ((adr = PC) + 2) & WMASK; - else { - R[reg] = ((adr = R[reg]) + 2) & WMASK; - recq[recqptr++] = RQ_REC (AIN|RW, reg); - } - return adr; -case 3: /* @(R)+ */ - if (reg == 7) PC = ((adr = PC) + 2) & WMASK; - else { - R[reg] = ((adr = R[reg]) + 2) & WMASK; - recq[recqptr++] = RQ_REC (AIN|RW, reg); - } - return RdMemW (adr); -case 4: /* -(R) */ - if (reg == 7) adr = PC = (PC - 2) & WMASK; - else { - adr = R[reg] = (R[reg] - 2) & WMASK; - recq[recqptr++] = RQ_REC (ADC|RW, reg); - } - return adr; -case 5: /* @-(R) */ - if (reg == 7) adr = PC = (PC - 2) & WMASK; - else { - adr = R[reg] = (R[reg] - 2) & WMASK; - recq[recqptr++] = RQ_REC (ADC|RW, reg); - } - return RdMemW (adr); -case 6: /* d(r) */ - adr = RdMemW (PC); - PC = (PC + 2) & WMASK; - if (reg == 7) return ((PC + adr) & WMASK); - else return ((R[reg] + adr) & WMASK); -case 7: /* @d(R) */ - adr = RdMemW (PC); - PC = (PC + 2) & WMASK; - if (reg == 7) adr = (PC + adr) & WMASK; - else adr = (R[reg] + adr) & WMASK; - return RdMemW (adr); - } /* end switch */ +reg = spec & 07; /* register number */ +switch (spec >> 3) { /* decode spec<5:3> */ + + default: /* can't get here */ + case 1: /* (R) */ + if (reg == 7) return (PC & WMASK); + else return (R[reg] & WMASK); + + case 2: /* (R)+ */ + if (reg == 7) PC = ((adr = PC) + 2) & WMASK; + else { + R[reg] = ((adr = R[reg]) + 2) & WMASK; + recq[recqptr++] = RQ_REC (AIN|RW, reg); + } + return adr; + + case 3: /* @(R)+ */ + if (reg == 7) PC = ((adr = PC) + 2) & WMASK; + else { + R[reg] = ((adr = R[reg]) + 2) & WMASK; + recq[recqptr++] = RQ_REC (AIN|RW, reg); + } + return RdMemW (adr); + + case 4: /* -(R) */ + if (reg == 7) adr = PC = (PC - 2) & WMASK; + else { + adr = R[reg] = (R[reg] - 2) & WMASK; + recq[recqptr++] = RQ_REC (ADC|RW, reg); + } + return adr; + + case 5: /* @-(R) */ + if (reg == 7) adr = PC = (PC - 2) & WMASK; + else { + adr = R[reg] = (R[reg] - 2) & WMASK; + recq[recqptr++] = RQ_REC (ADC|RW, reg); + } + return RdMemW (adr); + + case 6: /* d(r) */ + adr = RdMemW (PC); + PC = (PC + 2) & WMASK; + if (reg == 7) return ((PC + adr) & WMASK); + else return ((R[reg] + adr) & WMASK); + + case 7: /* @d(R) */ + adr = RdMemW (PC); + PC = (PC + 2) & WMASK; + if (reg == 7) adr = (PC + adr) & WMASK; + else adr = (R[reg] + adr) & WMASK; + return RdMemW (adr); + } /* end switch */ } int32 GeteaB (int32 spec) { int32 adr, reg; -reg = spec & 07; /* reg number */ -switch (spec >> 3) { /* decode spec<5:3> */ -default: /* can't get here */ -case 1: /* (R) */ - if (reg == 7) return (PC & WMASK); - else return (R[reg] & WMASK); -case 2: /* (R)+ */ - if (reg == 7) PC = ((adr = PC) + 2) & WMASK; - else if (reg == 6) { - R[reg] = ((adr = R[reg]) + 2) & WMASK; - recq[recqptr++] = RQ_REC (AIN|RW, reg); - } - else { - R[reg] = ((adr = R[reg]) + 1) & WMASK; - recq[recqptr++] = RQ_REC (AIN|RB, reg); - } - return adr; -case 3: /* @(R)+ */ - if (reg == 7) PC = ((adr = PC) + 2) & WMASK; - else { - R[reg] = ((adr = R[reg]) + 2) & WMASK; - recq[recqptr++] = RQ_REC (AIN|RW, reg); - } - return RdMemW (adr); -case 4: /* -(R) */ - if (reg == 7) adr = PC = (PC - 2) & WMASK; - else if (reg == 6) { - adr = R[reg] = (R[reg] - 2) & WMASK; - recq[recqptr++] = RQ_REC (ADC|RW, reg); - } - else { - adr = R[reg] = (R[reg] - 1) & WMASK; - recq[recqptr++] = RQ_REC (ADC|RB, reg); - } - return adr; -case 5: /* @-(R) */ - if (reg == 7) adr = PC = (PC - 2) & WMASK; - else { - adr = R[reg] = (R[reg] - 2) & WMASK; - recq[recqptr++] = RQ_REC (ADC|RW, reg); - } - return RdMemW (adr); -case 6: /* d(r) */ - adr = RdMemW (PC); - PC = (PC + 2) & WMASK; - if (reg == 7) return ((PC + adr) & WMASK); - else return ((R[reg] + adr) & WMASK); -case 7: /* @d(R) */ - adr = RdMemW (PC); - PC = (PC + 2) & WMASK; - if (reg == 7) adr = (PC + adr) & WMASK; - else adr = (R[reg] + adr) & WMASK; - return RdMemW (adr); - } /* end switch */ +reg = spec & 07; /* reg number */ +switch (spec >> 3) { /* decode spec<5:3> */ + + default: /* can't get here */ + case 1: /* (R) */ + if (reg == 7) return (PC & WMASK); + else return (R[reg] & WMASK); + + case 2: /* (R)+ */ + if (reg == 7) PC = ((adr = PC) + 2) & WMASK; + else if (reg == 6) { + R[reg] = ((adr = R[reg]) + 2) & WMASK; + recq[recqptr++] = RQ_REC (AIN|RW, reg); + } + else { + R[reg] = ((adr = R[reg]) + 1) & WMASK; + recq[recqptr++] = RQ_REC (AIN|RB, reg); + } + return adr; + + case 3: /* @(R)+ */ + if (reg == 7) PC = ((adr = PC) + 2) & WMASK; + else { + R[reg] = ((adr = R[reg]) + 2) & WMASK; + recq[recqptr++] = RQ_REC (AIN|RW, reg); + } + return RdMemW (adr); + + case 4: /* -(R) */ + if (reg == 7) adr = PC = (PC - 2) & WMASK; + else if (reg == 6) { + adr = R[reg] = (R[reg] - 2) & WMASK; + recq[recqptr++] = RQ_REC (ADC|RW, reg); + } + else { + adr = R[reg] = (R[reg] - 1) & WMASK; + recq[recqptr++] = RQ_REC (ADC|RB, reg); + } + return adr; + + case 5: /* @-(R) */ + if (reg == 7) adr = PC = (PC - 2) & WMASK; + else { + adr = R[reg] = (R[reg] - 2) & WMASK; + recq[recqptr++] = RQ_REC (ADC|RW, reg); + } + return RdMemW (adr); + + case 6: /* d(r) */ + adr = RdMemW (PC); + PC = (PC + 2) & WMASK; + if (reg == 7) return ((PC + adr) & WMASK); + else return ((R[reg] + adr) & WMASK); + + case 7: /* @d(R) */ + adr = RdMemW (PC); + PC = (PC + 2) & WMASK; + if (reg == 7) adr = (PC + adr) & WMASK; + else adr = (R[reg] + adr) & WMASK; + return RdMemW (adr); + } /* end switch */ } - + /* Memory and register access routines */ int32 RdMemW (int32 a) @@ -996,7 +1008,7 @@ if (rn == 7) { CMODE_JUMP (val); } else R[rn] = val; return; } - + #else /* Subset VAX @@ -1009,7 +1021,7 @@ extern jmp_buf save_env; t_bool BadCmPSL (int32 newpsl) { -return TRUE; /* always bad */ +return TRUE; /* always bad */ } int32 op_cmode (int32 cc) diff --git a/VAX/vax_cpu.c b/VAX/vax_cpu.c index e1286e02..9bf237a2 100644 --- a/VAX/vax_cpu.c +++ b/VAX/vax_cpu.c @@ -19,112 +19,111 @@ 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 + 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 VAX central processor + cpu VAX central processor - 13-Jan-05 RMS Fixed initial state of cpu_extmem - 06-Nov-04 RMS Added =n to SHOW HISTORY - 30-Sep-04 RMS Added octaword specifier decodes and instructions - Moved model-specific routines to system module - 02-Sep-04 RMS Fixed bug in EMODD/G, second word of quad dst not probed - 28-Jun-04 RMS Fixed bug in DIVBx, DIVWx (reported by Peter Trimmel) - 18-Apr-04 RMS Added octaword macros - 25-Jan-04 RMS Removed local debug logging support - RMS,MP Added extended physical memory support - 31-Dec-03 RMS Fixed bug in set_cpu_hist - 21-Dec-03 RMS Added autoconfiguration controls - 29-Oct-03 RMS Fixed WriteB declaration (found by Mark Pizzolato) - 23-Sep-03 RMS Revised instruction history for dynamic sizing - 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 + 16-Aug-05 RMS Fixed C++ declaration and cast problems + 13-Jan-05 RMS Fixed initial state of cpu_extmem + 06-Nov-04 RMS Added =n to SHOW HISTORY + 30-Sep-04 RMS Added octaword specifier decodes and instructions + Moved model-specific routines to system module + 02-Sep-04 RMS Fixed bug in EMODD/G, second word of quad dst not probed + 28-Jun-04 RMS Fixed bug in DIVBx, DIVWx (reported by Peter Trimmel) + 18-Apr-04 RMS Added octaword macros + 25-Jan-04 RMS Removed local debug logging support + RMS,MP Added extended physical memory support + 31-Dec-03 RMS Fixed bug in set_cpu_hist + 21-Dec-03 RMS Added autoconfiguration controls + 29-Oct-03 RMS Fixed WriteB declaration (found by Mark Pizzolato) + 23-Sep-03 RMS Revised instruction history for dynamic sizing + 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 VAX has a variable length instruction format with up to six operands: + 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 - opcode byte - operand 1 specifier - : - operand n specifier + 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 + 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]] + 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 + 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. @@ -132,106 +131,110 @@ 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). + 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 + 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_EXTM (UNIT_V_UF + 1) /* ext memory enable */ -#define UNIT_V_MSIZE (UNIT_V_UF + 2) /* dummy */ -#define UNIT_CONH (1u << UNIT_V_CONH) -#define UNIT_EXTM (1u << UNIT_V_EXTM) -#define UNIT_MSIZE (1u << UNIT_V_MSIZE) -#define GET_CUR acc = ACC_MASK (PSL_GETCUR (PSL)) +#define OP_MEM -1 +#define UNIT_V_CONH (UNIT_V_UF + 0) /* halt to console */ +#define UNIT_V_EXTM (UNIT_V_UF + 1) /* ext memory enable */ +#define UNIT_V_MSIZE (UNIT_V_UF + 2) /* dummy */ +#define UNIT_CONH (1u << UNIT_V_CONH) +#define UNIT_EXTM (1u << UNIT_V_EXTM) +#define UNIT_MSIZE (1u << UNIT_V_MSIZE) +#define GET_CUR acc = ACC_MASK (PSL_GETCUR (PSL)) -#define OPND_SIZE 20 -#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 CHECK_FOR_AP if (rn >= nAP) RSVD_ADDR_FAULT -#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 { \ - if (rn >= nSP) RSVD_ADDR_FAULT; \ - R[rn] = rl; \ - R[rn + 1] = rh; } +#define OPND_SIZE 20 +#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 CHECK_FOR_AP if (rn >= nAP) RSVD_ADDR_FAULT +#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 { \ + if (rn >= nSP) RSVD_ADDR_FAULT; \ + R[rn] = rl; \ + R[rn + 1] = rh; \ + } -#define HIST_MIN 64 -#define HIST_MAX 65536 -struct InstHistory { - int32 iPC; - int32 PSL; - int32 opc; - int32 brdest; - int32 opnd[OPND_SIZE]; }; +#define HIST_MIN 64 +#define HIST_MAX 65536 -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 */ +typedef struct { + int32 iPC; + int32 PSL; + int32 opc; + int32 brdest; + int32 opnd[OPND_SIZE]; + } InstHistory; + +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 P1BR = 0; /* P1 mem mgt */ int32 P1LR = 0; -int32 SBR = 0; /* S0 mem mgt */ +int32 SBR = 0; /* S0 mem mgt */ int32 SLR = 0; -int32 SISR; /* swre int req */ -int32 ASTLVL; /* AST level */ -int32 mapen; /* map enable */ -int32 pme; /* perf mon enable */ -int32 trpirq; /* trap/intr req */ -int32 in_ie = 0; /* in exc, int */ -int32 recq[6]; /* recovery queue */ -int32 recqptr; /* recq pointer */ -int32 hlt_pin = 0; /* HLT pin intr */ +int32 SISR; /* swre int req */ +int32 ASTLVL; /* AST level */ +int32 mapen; /* map enable */ +int32 pme; /* perf mon enable */ +int32 trpirq; /* trap/intr req */ +int32 in_ie = 0; /* in exc, int */ +int32 recq[6]; /* recovery queue */ +int32 recqptr; /* recq pointer */ +int32 hlt_pin = 0; /* HLT pin intr */ int32 mem_err = 0; int32 crd_err = 0; -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 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 mchk_va, mchk_ref; /* mem ref param */ -int32 ibufl, ibufh; /* prefetch buf */ -int32 ibcnt, ppc; /* prefetch ctl */ -int32 cpu_extmem = 1; /* extended memory */ +int32 mchk_va, mchk_ref; /* mem ref param */ +int32 ibufl, ibufh; /* prefetch buf */ +int32 ibcnt, ppc; /* prefetch ctl */ +int32 cpu_extmem = 1; /* extended memory */ jmp_buf save_env; -REG *pcq_r = NULL; /* PC queue reg ptr */ -int32 pcq[PCQ_SIZE] = { 0 }; /* PC queue */ -struct InstHistory *hst = NULL; /* instruction history */ +REG *pcq_r = NULL; /* PC queue reg ptr */ +int32 pcq[PCQ_SIZE] = { 0 }; /* PC queue */ +InstHistory *hst = NULL; /* instruction history */ const uint32 byte_mask[33] = { 0x00000000, 0x00000001, 0x00000003, 0x00000007, 0x0000000F, @@ -241,7 +244,8 @@ const uint32 byte_mask[33] = { 0x00000000, 0x0001FFFF, 0x0003FFFF, 0x0007FFFF, 0x000FFFFF, 0x001FFFFF, 0x003FFFFF, 0x007FFFFF, 0x00FFFFFF, 0x01FFFFFF, 0x03FFFFFF, 0x07FFFFFF, 0x0FFFFFFF, - 0x1FFFFFFF, 0x3FFFFFFF, 0x7FFFFFFF, 0xFFFFFFFF }; + 0x1FFFFFFF, 0x3FFFFFFF, 0x7FFFFFFF, 0xFFFFFFFF + }; const uint32 byte_sign[33] = { 0x00000000, 0x00000001, 0x00000002, 0x00000004, 0x00000008, 0x00000010, 0x00000020, 0x00000040, 0x00000080, @@ -250,15 +254,17 @@ const uint32 byte_sign[33] = { 0x00000000, 0x00010000, 0x00020000, 0x00040000, 0x00080000, 0x00100000, 0x00200000, 0x00400000, 0x00800000, 0x01000000, 0x02000000, 0x04000000, 0x08000000, - 0x10000000, 0x20000000, 0x40000000, 0x80000000 }; + 0x10000000, 0x20000000, 0x40000000, 0x80000000 + }; const uint32 align[4] = { - 0xFFFFFFFF, 0x00FFFFFF, 0x0000FFFF, 0x000000FF }; - + 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 int32 sim_brk_types, sim_brk_dflt, sim_brk_summ; /* breakpoint info */ extern UNIT clk_unit; extern t_stat build_dib_tab (void); @@ -349,277 +355,305 @@ t_stat cpu_show_hist (FILE *st, UNIT *uptr, int32 val, void *desc); t_stat cpu_show_virt (FILE *st, UNIT *uptr, int32 val, void *desc); int32 get_istr (int32 lnt, int32 acc); int32 ReadOcta (int32 va, int32 *opnd, int32 j, int32 acc); - + /* CPU data structures - cpu_dev CPU device descriptor - cpu_unit CPU unit - cpu_reg CPU register list - cpu_mod CPU modifier list + 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 + UNIT_EXTM, 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) }, - { FLDATA (MAPEN, mapen, 0) }, - { FLDATA (PME, pme, 0) }, - { HRDATA (TRPIRQ, trpirq, 8) }, - { FLDATA (CRDERR, crd_err, 0) }, - { FLDATA (MEMERR, mem_err, 0) }, - { FLDATA (HLTPIN, hlt_pin, 0) }, - { 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 } }; + { 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) }, + { FLDATA (MAPEN, mapen, 0) }, + { FLDATA (PME, pme, 0) }, + { HRDATA (TRPIRQ, trpirq, 8) }, + { FLDATA (CRDERR, crd_err, 0) }, + { FLDATA (MEMERR, mem_err, 0) }, + { FLDATA (HLTPIN, hlt_pin, 0) }, + { 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_EXTM, UNIT_EXTM, NULL, "EXTENDEDMEMORY", &cpu_set_extm }, - { UNIT_EXTM, 0, NULL, "NOEXTENDEDMEMORY", &cpu_set_extm }, - { 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 << 25) + (1u << 24), NULL, "48M", &cpu_set_size }, - { UNIT_MSIZE, (1u << 26), NULL, "64M", &cpu_set_size }, - { UNIT_MSIZE, (1u << 27), NULL, "128M", &cpu_set_size }, - { UNIT_MSIZE, (1u << 28), NULL, "256M", &cpu_set_size }, - { UNIT_MSIZE, (1u << 29), NULL, "512M", &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|MTAB_SHP, 0, "HISTORY", "HISTORY", - &cpu_set_hist, &cpu_show_hist }, - { MTAB_XTD|MTAB_VDV|MTAB_NMO|MTAB_SHP, 0, "VIRTUAL", NULL, - NULL, &cpu_show_virt }, - { 0 } }; + { UNIT_EXTM, UNIT_EXTM, NULL, "EXTENDEDMEMORY", &cpu_set_extm }, + { UNIT_EXTM, 0, NULL, "NOEXTENDEDMEMORY", &cpu_set_extm }, + { 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 << 25) + (1u << 24), NULL, "48M", &cpu_set_size }, + { UNIT_MSIZE, (1u << 26), NULL, "64M", &cpu_set_size }, + { UNIT_MSIZE, (1u << 27), NULL, "128M", &cpu_set_size }, + { UNIT_MSIZE, (1u << 28), NULL, "256M", &cpu_set_size }, + { UNIT_MSIZE, (1u << 29), NULL, "512M", &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|MTAB_SHP, 0, "HISTORY", "HISTORY", + &cpu_set_hist, &cpu_show_hist }, + { MTAB_XTD|MTAB_VDV|MTAB_NMO|MTAB_SHP, 0, "VIRTUAL", NULL, + NULL, &cpu_show_virt }, + { 0 } + }; DEBTAB cpu_deb[] = { - { "INTEXC", LOG_CPU_I }, - { "REI", LOG_CPU_R }, - { "CONTEXT", LOG_CPU_P }, - { NULL, 0 } }; + { "INTEXC", LOG_CPU_I }, + { "REI", LOG_CPU_R }, + { "CONTEXT", LOG_CPU_P }, + { NULL, 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 | DEV_DEBUG, 0, - cpu_deb, &cpu_set_size, NULL }; - + "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 | DEV_DEBUG, 0, + cpu_deb, &cpu_set_size, NULL + }; + t_stat sim_instr (void) { -volatile int32 opc, cc; /* used by setjmp */ -int32 acc; /* set by setjmp */ +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 */ -if ((PSL & PSL_MBZ) || /* validate PSL */ - ((PSL & PSL_CM) && BadCmPSL (PSL)) || /* validate PSL */ - ((PSL_GETCUR (PSL) != KERN) && /* esu => is, ipl = 0 */ - (PSL & (PSL_IS|PSL_IPL))) || - ((PSL & PSL_IS) && ((PSL & PSL_IPL) == 0))) /* is => ipl > 0 */ - return SCPE_STOP; -cc = PSL & CC_MASK; /* split PSL */ +if ((r = build_dib_tab ()) != SCPE_OK) return r; /* build, chk dib_tab */ +if ((PSL & PSL_MBZ) || /* validate PSL */ + ((PSL & PSL_CM) && BadCmPSL (PSL)) || /* validate PSL */ + ((PSL_GETCUR (PSL) != KERN) && /* esu => is, ipl = 0 */ + (PSL & (PSL_IS|PSL_IPL))) || + ((PSL & PSL_IS) && ((PSL & PSL_IPL) == 0))) /* is => ipl > 0 */ + return SCPE_STOP; +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 */ +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, delta; + if ((PSL & PSL_FPD) == 0) { /* FPD? no recovery */ + for (i = 0; i < recqptr; i++) { /* unwind inst */ + int32 rrn, rlnt; + rrn = RQ_GETRN (recq[i]); /* recover reg # */ + rlnt = DR_LNT (RQ_GETLNT (recq[i])); /* recovery lnt */ + if (recq[i] & RQ_DIR) R[rrn] = R[rrn] - rlnt; + else R[rrn] = R[rrn] + rlnt; + } + } + recqptr = 0; /* clear queue */ + delta = PC - fault_PC; /* save delta PC */ + SETPC (fault_PC); /* restore PC */ + switch (-abortval) { /* case on abort code */ + + case SCB_RESIN: /* rsrv inst fault */ + case SCB_RESAD: /* rsrv addr fault */ + case SCB_RESOP: /* rsrv opnd 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_CMODE: /* comp mode fault */ + 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: /* ACV fault */ + case SCB_TNV: /* TNV fault */ + 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? */ + cc = machine_check (p1, opc, cc, delta); /* system specific */ + in_ie = 0; + GET_CUR; /* PSL changed */ + break; + + case 1: /* interrupt */ + break; /* just proceed */ + default: /* other */ + badabo = abortval; /* save code */ + ABORT (STOP_UNKABO); /* panic */ + } /* end case */ + } /* end else */ -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, delta; - if ((PSL & PSL_FPD) == 0) { /* FPD? no recovery */ - for (i = 0; i < recqptr; i++) { /* unwind inst */ - int32 rrn, rlnt; - rrn = RQ_GETRN (recq[i]); /* recover reg # */ - rlnt = DR_LNT (RQ_GETLNT (recq[i])); /* recovery lnt */ - if (recq[i] & RQ_DIR) R[rrn] = R[rrn] - rlnt; - else R[rrn] = R[rrn] + rlnt; } } - recqptr = 0; /* clear queue */ - delta = PC - fault_PC; /* save delta PC */ - SETPC (fault_PC); /* restore PC */ - switch (-abortval) { /* case on abort code */ - case SCB_RESIN: /* rsrv inst fault */ - case SCB_RESAD: /* rsrv addr fault */ - case SCB_RESOP: /* rsrv opnd 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_CMODE: /* comp mode fault */ - 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: /* ACV fault */ - case SCB_TNV: /* TNV fault */ - 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? */ - cc = machine_check (p1, opc, cc, delta); /* system specific */ - in_ie = 0; - GET_CUR; /* PSL changed */ - 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); } + 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 */ -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 */ + 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 + - 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? */ - hlt_pin = 0; /* clear intr */ - trpirq = 0; /* clear everything */ - cc = con_halt (CON_HLTPIN, cc); /* invoke firmware */ - continue; } /* continue */ - 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 (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? */ + hlt_pin = 0; /* clear intr */ + trpirq = 0; /* clear everything */ + cc = con_halt (CON_HLTPIN, cc); /* invoke firmware */ + continue; /* continue */ + } + 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_CM|PSL_TP|PSW_T)) { /* PSL event? */ - 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 (PSL & PSL_CM) { /* compat mode? */ - cc = op_cmode (cc); /* exec instr */ - continue; } /* skip fetch */ - } /* end PSL event */ + if (PSL & (PSL_CM|PSL_TP|PSW_T)) { /* PSL event? */ + 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 (PSL & PSL_CM) { /* compat mode? */ + cc = op_cmode (cc); /* exec instr */ + continue; /* skip fetch */ + } + } /* end PSL event */ -if (sim_brk_summ && sim_brk_test (PC, SWMASK ('E'))) { /* breakpoint? */ - ABORT (STOP_IBKPT); } /* stop simulation */ + 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 */ -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 - r.o opnd[j:j+3] = value of operand - a.bwlqo opnd[j] = address of operand - m.bwl opnd[j] = value of operand - m.q opnd[j:j+1] = value of operand - m.o opnd[j:j+3] = value of operand - w.bwlqo opnd[j] = register/memory flag - opnd[j+1] = memory address + r.bwl opnd[j] = value of operand + r.q opnd[j:j+1] = value of operand + r.o opnd[j:j+3] = value of operand + a.bwlqo opnd[j] = address of operand + m.bwl opnd[j] = value of operand + m.q opnd[j:j+1] = value of operand + m.o opnd[j:j+3] = value of operand + w.bwlqo 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 @@ -627,1748 +661,1932 @@ else { numspec = numspec & DR_NSPMASK; /* get # specifiers */ 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 & 1)); - 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 */ + 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 & 1)); + 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|RO: case SH1|RO: case SH2|RO: case SH3|RO: - opnd[j++] = spec; - opnd[j++] = 0; - opnd[j++] = 0; - 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; - case SH0|RH: case SH1|RH: case SH2|RH: case SH3|RH: - opnd[j++] = ((spec & 0x7) << 29) | (0x4000 | ((spec >> 3) & 0x7)); - opnd[j++] = 0; - opnd[j++] = 0; - opnd[j++] = 0; - break; - + 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|RO: case SH1|RO: case SH2|RO: case SH3|RO: + opnd[j++] = spec; + opnd[j++] = 0; + opnd[j++] = 0; + 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; + case SH0|RH: case SH1|RH: case SH2|RH: case SH3|RH: + opnd[j++] = ((spec & 0x7) << 29) | (0x4000 | ((spec >> 3) & 0x7)); + opnd[j++] = 0; + opnd[j++] = 0; + 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[(rn + 1) & RGMASK]; - case GRN|WB: case GRN|WW: case GRN|WL: case GRN|WQ: case GRN|WO: - 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[rn + 1]; - break; - case GRN|RO: case GRN|RH: case GRN|MO: - CHECK_FOR_AP; - opnd[j++] = R[rn]; - opnd[j++] = R[rn + 1]; - opnd[j++] = R[rn + 2]; - opnd[j++] = R[rn + 3]; - break; + 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[(rn + 1) & RGMASK]; + case GRN|WB: case GRN|WW: case GRN|WL: case GRN|WQ: case GRN|WO: + 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[rn + 1]; + break; + case GRN|RO: case GRN|RH: case GRN|MO: + CHECK_FOR_AP; + opnd[j++] = R[rn]; + opnd[j++] = R[rn + 1]; + opnd[j++] = R[rn + 2]; + opnd[j++] = R[rn + 3]; + break; /* Register deferred, autodecrement */ - case RGD|VB: - case RGD|WB: case RGD|WW: case RGD|WL: case RGD|WQ: case RGD|WO: - opnd[j++] = OP_MEM; - case RGD|AB: case RGD|AW: case RGD|AL: case RGD|AQ: case RGD|AO: - CHECK_FOR_PC; - va = opnd[j++] = R[rn]; - break; - case ADC|VB: - case ADC|WB: case ADC|WW: case ADC|WL: case ADC|WQ: case ADC|WO: - opnd[j++] = OP_MEM; - case ADC|AB: case ADC|AW: case ADC|AL: case ADC|AQ: case ADC|AO: - CHECK_FOR_PC; - va = opnd[j++] = R[rn] = R[rn] - DR_LNT (disp); - recq[recqptr++] = RQ_REC (disp, rn); - 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++] = RQ_REC (disp, rn); - 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++] = RQ_REC (disp, rn); - 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; - case ADC|RO: case ADC|RH: case ADC|MO: - R[rn] = R[rn] - 16; - recq[recqptr++] = RQ_REC (disp, rn); - case RGD|RO: case RGD|RH: case RGD|MO: - CHECK_FOR_PC; - j = ReadOcta (va = R[rn], opnd, j, acc); - break; - + case RGD|VB: + case RGD|WB: case RGD|WW: case RGD|WL: case RGD|WQ: case RGD|WO: + opnd[j++] = OP_MEM; + case RGD|AB: case RGD|AW: case RGD|AL: case RGD|AQ: case RGD|AO: + CHECK_FOR_PC; + va = opnd[j++] = R[rn]; + break; + case ADC|VB: + case ADC|WB: case ADC|WW: case ADC|WL: case ADC|WQ: case ADC|WO: + opnd[j++] = OP_MEM; + case ADC|AB: case ADC|AW: case ADC|AL: case ADC|AQ: case ADC|AO: + CHECK_FOR_PC; + va = opnd[j++] = R[rn] = R[rn] - DR_LNT (disp); + recq[recqptr++] = RQ_REC (disp, rn); + 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++] = RQ_REC (disp, rn); + 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++] = RQ_REC (disp, rn); + 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; + case ADC|RO: case ADC|RH: case ADC|MO: + R[rn] = R[rn] - 16; + recq[recqptr++] = RQ_REC (disp, rn); + case RGD|RO: case RGD|RH: case RGD|MO: + CHECK_FOR_PC; + j = ReadOcta (va = R[rn], opnd, j, acc); + break; + /* Autoincrement */ - case AIN|VB: - case AIN|WB: case AIN|WW: case AIN|WL: case AIN|WQ: case AIN|WO: -/* CHECK_FOR_PC; */ - opnd[j++] = OP_MEM; - case AIN|AB: case AIN|AW: case AIN|AL: case AIN|AQ: case AIN|AO: - va = opnd[j++] = R[rn]; - if (rn == nPC) { - if (DR_LNT (disp) >= L_QUAD) { - GET_ISTR (temp, L_LONG); - GET_ISTR (temp, L_LONG); - if (DR_LNT (disp) == L_OCTA) { - 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++] = RQ_REC (disp, rn); } - 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++] = RQ_REC (disp, rn); } - 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++] = RQ_REC (disp, rn); } - break; - case AIN|MO: -/* CHECK_FOR_PC; */ - case AIN|RO: case AIN|RH: - va = R[rn]; - if (rn == nPC) { - GET_ISTR (opnd[j++], L_LONG); - GET_ISTR (opnd[j++], L_LONG); - GET_ISTR (opnd[j++], L_LONG); - GET_ISTR (opnd[j++], L_LONG); } - else { - j = ReadOcta (va, opnd, j, acc); - R[rn] = R[rn] + 16; - recq[recqptr++] = RQ_REC (disp, rn); } - break; + case AIN|VB: + case AIN|WB: case AIN|WW: case AIN|WL: case AIN|WQ: case AIN|WO: +/* CHECK_FOR_PC; */ + opnd[j++] = OP_MEM; + case AIN|AB: case AIN|AW: case AIN|AL: case AIN|AQ: case AIN|AO: + va = opnd[j++] = R[rn]; + if (rn == nPC) { + if (DR_LNT (disp) >= L_QUAD) { + GET_ISTR (temp, L_LONG); + GET_ISTR (temp, L_LONG); + if (DR_LNT (disp) == L_OCTA) { + 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++] = RQ_REC (disp, rn); + } + 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++] = RQ_REC (disp, rn); + } + 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++] = RQ_REC (disp, rn); + } + break; + case AIN|MO: +/* CHECK_FOR_PC; */ + case AIN|RO: case AIN|RH: + va = R[rn]; + if (rn == nPC) { + GET_ISTR (opnd[j++], L_LONG); + GET_ISTR (opnd[j++], L_LONG); + GET_ISTR (opnd[j++], L_LONG); + GET_ISTR (opnd[j++], L_LONG); + } + else { + j = ReadOcta (va, opnd, j, acc); + R[rn] = R[rn] + 16; + recq[recqptr++] = RQ_REC (disp, rn); + } + break; /* Autoincrement deferred */ - case AID|VB: - case AID|WB: case AID|WW: case AID|WL: case AID|WQ: case AID|WO: - opnd[j++] = OP_MEM; - case AID|AB: case AID|AW: case AID|AL: case AID|AQ: case AID|AO: - 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++] = RQ_REC (AID|RL, rn); } - 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++] = RQ_REC (AID|RL, rn); } - 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++] = RQ_REC (AID|RL, rn); } - opnd[j++] = Read (va, L_LONG, RA); - opnd[j++] = Read (va + 4, L_LONG, RA); - break; - case AID|RO: case AID|RH: case AID|MO: - if (rn == nPC) { GET_ISTR (va, L_LONG); } - else { - va = Read (R[rn], L_LONG, RA); - R[rn] = R[rn] + 4; - recq[recqptr++] = RQ_REC (AID|RL, rn); } - j = ReadOcta (va, opnd, j, acc); - break; - + case AID|VB: + case AID|WB: case AID|WW: case AID|WL: case AID|WQ: case AID|WO: + opnd[j++] = OP_MEM; + case AID|AB: case AID|AW: case AID|AL: case AID|AQ: case AID|AO: + 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++] = RQ_REC (AID|RL, rn); + } + 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++] = RQ_REC (AID|RL, rn); + } + 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++] = RQ_REC (AID|RL, rn); + } + opnd[j++] = Read (va, L_LONG, RA); + opnd[j++] = Read (va + 4, L_LONG, RA); + break; + case AID|RO: case AID|RH: case AID|MO: + if (rn == nPC) { + GET_ISTR (va, L_LONG); + } + else { + va = Read (R[rn], L_LONG, RA); + R[rn] = R[rn] + 4; + recq[recqptr++] = RQ_REC (AID|RL, rn); + } + j = ReadOcta (va, opnd, j, acc); + break; + /* Byte displacement */ - case BDP|VB: - case BDP|WB: case BDP|WW: case BDP|WL: case BDP|WQ: case BDP|WO: - opnd[j++] = OP_MEM; - case BDP|AB: case BDP|AW: case BDP|AL: case BDP|AQ: case BDP|AO: - 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; - case BDP|RO: case BDP|RH: case BDP|MO: - GET_ISTR (temp, L_BYTE); - va = R[rn] + SXTB (temp); - j = ReadOcta (va, opnd, j, acc); - break; + case BDP|VB: + case BDP|WB: case BDP|WW: case BDP|WL: case BDP|WQ: case BDP|WO: + opnd[j++] = OP_MEM; + case BDP|AB: case BDP|AW: case BDP|AL: case BDP|AQ: case BDP|AO: + 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; + case BDP|RO: case BDP|RH: case BDP|MO: + GET_ISTR (temp, L_BYTE); + va = R[rn] + SXTB (temp); + j = ReadOcta (va, opnd, j, acc); + break; /* Byte displacement deferred */ - case BDD|VB: - case BDD|WB: case BDD|WW: case BDD|WL: case BDD|WQ: case BDD|WO: - opnd[j++] = OP_MEM; - case BDD|AB: case BDD|AW: case BDD|AL: case BDD|AQ: case BDD|AO: - 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; - case BDD|RO: case BDD|RH: case BDD|MO: - GET_ISTR (temp, L_BYTE); - iad = R[rn] + SXTB (temp); - va = Read (iad, L_LONG, RA); - j = ReadOcta (va, opnd, j, acc); - break; - + case BDD|VB: + case BDD|WB: case BDD|WW: case BDD|WL: case BDD|WQ: case BDD|WO: + opnd[j++] = OP_MEM; + case BDD|AB: case BDD|AW: case BDD|AL: case BDD|AQ: case BDD|AO: + 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; + case BDD|RO: case BDD|RH: case BDD|MO: + GET_ISTR (temp, L_BYTE); + iad = R[rn] + SXTB (temp); + va = Read (iad, L_LONG, RA); + j = ReadOcta (va, opnd, j, acc); + break; + /* Word displacement */ - case WDP|VB: - case WDP|WB: case WDP|WW: case WDP|WL: case WDP|WQ: case WDP|WO: - opnd[j++] = OP_MEM; - case WDP|AB: case WDP|AW: case WDP|AL: case WDP|AQ: case WDP|AO: - 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; - case WDP|MO: case WDP|RO: case WDP|RH: - GET_ISTR (temp, L_WORD); - va = R[rn] + SXTW (temp); - j = ReadOcta (va, opnd, j, acc); - break; + case WDP|VB: + case WDP|WB: case WDP|WW: case WDP|WL: case WDP|WQ: case WDP|WO: + opnd[j++] = OP_MEM; + case WDP|AB: case WDP|AW: case WDP|AL: case WDP|AQ: case WDP|AO: + 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; + case WDP|MO: case WDP|RO: case WDP|RH: + GET_ISTR (temp, L_WORD); + va = R[rn] + SXTW (temp); + j = ReadOcta (va, opnd, j, acc); + break; /* Word displacement deferred */ - case WDD|VB: - case WDD|WB: case WDD|WW: case WDD|WL: case WDD|WQ: case WDD|WO: - opnd[j++] = OP_MEM; - case WDD|AB: case WDD|AW: case WDD|AL: case WDD|AQ: case WDD|AO: - 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; - case WDD|MO: case WDD|RO: case WDD|RH: - GET_ISTR (temp, L_WORD); - iad = R[rn] + SXTW (temp); - va = Read (iad, L_LONG, RA); - j = ReadOcta (va, opnd, j, acc); - break; - + case WDD|VB: + case WDD|WB: case WDD|WW: case WDD|WL: case WDD|WQ: case WDD|WO: + opnd[j++] = OP_MEM; + case WDD|AB: case WDD|AW: case WDD|AL: case WDD|AQ: case WDD|AO: + 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; + case WDD|MO: case WDD|RO: case WDD|RH: + GET_ISTR (temp, L_WORD); + iad = R[rn] + SXTW (temp); + va = Read (iad, L_LONG, RA); + j = ReadOcta (va, opnd, j, acc); + break; + /* Longword displacement */ - case LDP|VB: - case LDP|WB: case LDP|WW: case LDP|WL: case LDP|WQ: case LDP|WO: - opnd[j++] = OP_MEM; - case LDP|AB: case LDP|AW: case LDP|AL: case LDP|AQ: case LDP|AO: - 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; - case LDP|MO: case LDP|RO: case LDP|RH: - GET_ISTR (temp, L_LONG); - va = R[rn] + temp; - j = ReadOcta (va, opnd, j, acc); - break; + case LDP|VB: + case LDP|WB: case LDP|WW: case LDP|WL: case LDP|WQ: case LDP|WO: + opnd[j++] = OP_MEM; + case LDP|AB: case LDP|AW: case LDP|AL: case LDP|AQ: case LDP|AO: + 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; + case LDP|MO: case LDP|RO: case LDP|RH: + GET_ISTR (temp, L_LONG); + va = R[rn] + temp; + j = ReadOcta (va, opnd, j, acc); + break; /* Longword displacement deferred */ - case LDD|VB: - case LDD|WB: case LDD|WW: case LDD|WL: case LDD|WQ: case LDD|WO: - opnd[j++] = OP_MEM; - case LDD|AB: case LDD|AW: case LDD|AL: case LDD|AQ: case LDD|AO: - 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; - case LDD|MO: case LDD|RO: case LDD|RH: - GET_ISTR (temp, L_LONG); - iad = R[rn] + temp; - va = Read (iad, L_LONG, RA); - j = ReadOcta (va, opnd, j, acc); - break; - + case LDD|VB: + case LDD|WB: case LDD|WW: case LDD|WL: case LDD|WQ: case LDD|WO: + opnd[j++] = OP_MEM; + case LDD|AB: case LDD|AW: case LDD|AL: case LDD|AQ: case LDD|AO: + 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; + case LDD|MO: case LDD|RO: case LDD|RH: + GET_ISTR (temp, L_LONG); + iad = R[rn] + temp; + va = Read (iad, L_LONG, RA); + j = ReadOcta (va, opnd, j, acc); + break; + /* Index */ - case IDX|VB: - case IDX|WB: case IDX|WW: case IDX|WL: case IDX|WQ: case IDX|WO: - case IDX|AB: case IDX|AW: case IDX|AL: case IDX|AQ: case IDX|AO: - case IDX|MB: case IDX|MW: case IDX|ML: case IDX|MQ: case IDX|MO: - case IDX|RB: case IDX|RW: case IDX|RL: case IDX|RQ: case IDX|RO: - case IDX|RF: case IDX|RD: case IDX|RG: case IDX|RH: - CHECK_FOR_PC; - index = R[rn] << (disp & DR_LNMASK); - GET_ISTR (spec, L_BYTE); - rn = spec & RGMASK; - switch (spec & ~RGMASK) { - case ADC: - R[rn] = R[rn] - DR_LNT (disp); - recq[recqptr++] = RQ_REC (ADC | (disp & DR_LNMASK), rn); - 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++] = RQ_REC (AIN | (disp & DR_LNMASK), rn); - 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++] = RQ_REC (AID|RL, rn); } - 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 & (DR_ACMASK|DR_LNMASK)) { /* case disp type */ - case WB: case WW: case WL: case WQ: case WO: - opnd[j++] = OP_MEM; - case AB: case AW: case AL: case AQ: case AO: - 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; - case RO: case MO: - j = ReadOcta (va = index, opnd, j, acc); - 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 */ + case IDX|VB: + case IDX|WB: case IDX|WW: case IDX|WL: case IDX|WQ: case IDX|WO: + case IDX|AB: case IDX|AW: case IDX|AL: case IDX|AQ: case IDX|AO: + case IDX|MB: case IDX|MW: case IDX|ML: case IDX|MQ: case IDX|MO: + case IDX|RB: case IDX|RW: case IDX|RL: case IDX|RQ: case IDX|RO: + case IDX|RF: case IDX|RD: case IDX|RG: case IDX|RH: + CHECK_FOR_PC; + index = R[rn] << (disp & DR_LNMASK); + GET_ISTR (spec, L_BYTE); + rn = spec & RGMASK; + switch (spec & ~RGMASK) { + case ADC: + R[rn] = R[rn] - DR_LNT (disp); + recq[recqptr++] = RQ_REC (ADC | (disp & DR_LNMASK), rn); + 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++] = RQ_REC (AIN | (disp & DR_LNMASK), rn); + 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++] = RQ_REC (AID|RL, rn); + } + 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 & (DR_ACMASK|DR_LNMASK)) { /* case disp type */ + case WB: case WW: case WL: case WQ: case WO: + opnd[j++] = OP_MEM; + case AB: case AW: case AL: case AQ: case AO: + 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; + case RO: case MO: + j = ReadOcta (va = index, opnd, j, acc); + 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) { - hst[hst_p].iPC = fault_PC; - hst[hst_p].PSL = PSL | cc; - hst[hst_p].opc = opc; - hst[hst_p].brdest = brdisp + PC; - for (i = 0; i < OPND_SIZE; i++) - hst[hst_p].opnd[i] = opnd[i]; - hst_p = hst_p + 1; - if (hst_p >= hst_lnt) hst_p = 0; - } - + if (hst_lnt) { + hst[hst_p].iPC = fault_PC; + hst[hst_p].PSL = PSL | cc; + hst[hst_p].opc = opc; + hst[hst_p].brdest = brdisp + PC; + for (i = 0; i < OPND_SIZE; i++) + hst[hst_p].opnd[i] = opnd[i]; + hst_p = hst_p + 1; + if (hst_p >= hst_lnt) hst_p = 0; + } + /* Dispatch to instructions */ -switch (opc) { + switch (opc) { /* Single operand instructions with dest, write only - CLRx dst.wx - spec = reg/memory flag - rn = register number - va = virtual address + 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; + 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 + 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; + + 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 + 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; + 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 + + 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; + 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 + + 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 MOVB: + WRITE_B (op0); /* result */ + CC_IIZP_B (op0); /* 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 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; -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 + 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; + 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 + 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 + 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; } - r = r & BMASK; /* mask to result */ - 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; } - r = r & WMASK; /* mask to result */ - 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; } - r = r & LMASK; /* mask to result */ - WRITE_L (r); /* write result */ - CC_IIZZ_L (r); /* set cc's */ - cc = cc | temp; /* error? set V */ - break; + 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; + } + r = r & BMASK; /* mask to result */ + 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; + } + r = r & WMASK; /* mask to result */ + 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; + } + r = r & LMASK; /* mask to result */ + 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; -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 - + 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; + 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 + 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)? LMASK: 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) & LMASK; /* 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; + 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)? LMASK: 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) & LMASK; /* 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) + 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; + 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) + 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; - + 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 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 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 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 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; + 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 + 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 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; -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 + 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; + 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 + 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; + 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 + 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 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 + 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; + 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 + 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; - + 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 + 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; + 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 + 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; + 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 + 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; + 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 + 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; - + 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 + 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; + 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; - + 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; + 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; - + 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 TSTF: case TSTD: + r = op_movfd (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 TSTG: + r = op_movg (op0); + CC_IIZZ_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 MOVF: + r = op_movfd (op0); + WRITE_L (r); + CC_IIZP_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 MOVD: + if ((r = op_movfd (op0)) == 0) op1 = 0; + WRITE_Q (r, op1); + CC_IIZP_FP (r); + 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 MOVG: + if ((r = op_movg (op0)) == 0) op1 = 0; + WRITE_Q (r, op1); + CC_IIZP_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 MNEGF: + r = op_mnegfd (op0); + WRITE_L (r); + CC_IIZZ_FP (r); + 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 MNEGD: + if ((r = op_mnegfd (op0)) == 0) op1 = 0; + WRITE_Q (r, op1); + 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 MNEGG: + if ((r = op_mnegg (op0)) == 0) op1 = 0; + WRITE_Q (r, op1); + 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; + 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) + 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; + 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) + 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_BYTE, WA); - Read ((op8 + 7) & LMASK, L_BYTE, 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 EMODD: + r = op_emodd (opnd, &rh, &temp, &flg); + if (op7 < 0) { + Read (op8, L_BYTE, WA); + Read ((op8 + 7) & LMASK, L_BYTE, 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_BYTE, WA); - Read ((op8 + 7) & LMASK, L_BYTE, 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_BYTE, WA); + Read ((op8 + 7) & LMASK, L_BYTE, 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 POLYF: + op_polyf (opnd, acc); + CC_IIZZ_FP (R[0]); + break; -case POLYD: - op_polyd (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; -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; + 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; /* CIS or emulated instructions */ -case CVTPL: -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_cis (opnd, cc, opc, acc); - break; + case CVTPL: + 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_cis (opnd, cc, opc, acc); + break; /* Octaword or reserved instructions */ -case PUSHAO: case MOVAO: case CLRO: case MOVO: -case TSTH: case MOVH: case MNEGH: case CMPH: -case CVTBH: case CVTWH: case CVTLH: -case CVTHB: case CVTHW: case CVTHL: case CVTRHL: -case CVTFH: case CVTDH: case CVTGH: -case CVTHF: case CVTHD: case CVTHG: -case ADDH2: case ADDH3: case SUBH2: case SUBH3: -case MULH2: case MULH3: case DIVH2: case DIVH3: -case ACBH: case POLYH: case EMODH: - cc = op_octa (opnd, cc, opc, acc, spec, va); - if (cc & LSIGN) { /* ACBH branch? */ - BRANCHW (brdisp); - cc = cc & CC_MASK; } /* mask off flag */ - break; + case PUSHAO: case MOVAO: case CLRO: case MOVO: + case TSTH: case MOVH: case MNEGH: case CMPH: + case CVTBH: case CVTWH: case CVTLH: + case CVTHB: case CVTHW: case CVTHL: case CVTRHL: + case CVTFH: case CVTDH: case CVTGH: + case CVTHF: case CVTHD: case CVTHG: + case ADDH2: case ADDH3: case SUBH2: case SUBH3: + case MULH2: case MULH3: case DIVH2: case DIVH3: + case ACBH: case POLYH: case EMODH: + cc = op_octa (opnd, cc, opc, acc, spec, va); + if (cc & LSIGN) { /* ACBH branch? */ + BRANCHW (brdisp); + cc = cc & CC_MASK; /* mask off flag */ + } + break; -default: - RSVD_INST_FAULT; - break; } /* end case op */ -} /* end for */ + default: + RSVD_INST_FAULT; + break; + } /* end case op */ + } /* end for */ ABORT (STOP_UNKNOWN); -} /* end sim_instr */ - +} /* 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 + 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 @@ -2386,26 +2604,31 @@ 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; } +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; } @@ -2419,7 +2642,7 @@ opnd[j++] = Read (va + 8, L_LONG, RA); opnd[j++] = Read (va + 12, L_LONG, RA); return j; } - + /* Reset */ t_stat cpu_reset (DEVICE *dptr) @@ -2431,7 +2654,7 @@ PSL = PSL_IS | PSL_IPL1F; SISR = 0; ASTLVL = 4; mapen = 0; -if (M == NULL) M = calloc (((uint32) MEMSIZE) >> 2, sizeof (int32)); +if (M == NULL) M = (uint32 *) calloc (((uint32) MEMSIZE) >> 2, sizeof (uint32)); if (M == NULL) return SCPE_MEM; pcq_r = find_reg ("PCQ", NULL, dptr); if (pcq_r) pcq_r->qptr = 0; @@ -2452,8 +2675,9 @@ 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; } + *vptr = (uint32) ReadB (addr); + return SCPE_OK; + } return SCPE_NXM; } @@ -2468,11 +2692,13 @@ 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; } + WriteB (addr, (int32) val); + return SCPE_OK; + } if (ADDR_IS_ROM (addr)) { - rom_wr_B (addr, (int32) val); - return SCPE_OK; } + rom_wr_B (addr, (int32) val); + return SCPE_OK; + } return SCPE_NXM; } @@ -2497,8 +2723,8 @@ if ((val <= 0) || (val > ((uptr->flags & UNIT_EXTM)? MAXMEMSIZE_X: 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)); + return SCPE_OK; +nM = (uint32 *) 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]; @@ -2517,21 +2743,24 @@ char *cptr = (char *) desc; 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" }; + "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) { - va = (uint32) get_uint (cptr, 16, 0xFFFFFFFF, &r); - if (r == SCPE_OK) { - pa = Test (va, RD, &st); - if (st == PR_OK) fprintf (of, "Virtual %-X = physical %-X", va, pa); - else fprintf (of, "Virtual %-X: %s", va, mm_str[st]); - return SCPE_OK; } } + va = (uint32) get_uint (cptr, 16, 0xFFFFFFFF, &r); + if (r == SCPE_OK) { + pa = Test (va, RD, &st); + if (st == PR_OK) fprintf (of, "Virtual %-X = physical %-X", va, pa); + else fprintf (of, "Virtual %-X: %s", va, mm_str[st]); + return SCPE_OK; + } + } fprintf (of, "Invalid argument"); return SCPE_OK; } @@ -2544,20 +2773,23 @@ int32 i, lnt; t_stat r; if (cptr == NULL) { - for (i = 0; i < hst_lnt; i++) hst[i].iPC = 0; - hst_p = 0; - return SCPE_OK; } + for (i = 0; i < hst_lnt; i++) hst[i].iPC = 0; + hst_p = 0; + return SCPE_OK; + } lnt = (int32) get_uint (cptr, 10, HIST_MAX, &r); if ((r != SCPE_OK) || (lnt && (lnt < HIST_MIN))) return SCPE_ARG; hst_p = 0; if (hst_lnt) { - free (hst); - hst_lnt = 0; - hst = NULL; } + free (hst); + hst_lnt = 0; + hst = NULL; + } if (lnt) { - hst = calloc (sizeof (struct InstHistory), lnt); - if (hst == NULL) return SCPE_MEM; - hst_lnt = lnt; } + hst = (InstHistory *) calloc (lnt, sizeof (InstHistory)); + if (hst == NULL) return SCPE_MEM; + hst_lnt = lnt; + } return SCPE_OK; } @@ -2568,57 +2800,58 @@ t_stat cpu_show_hist (FILE *st, UNIT *uptr, int32 val, void *desc) int32 i, j, k, di, disp, numspec, lnt; char *cptr = (char *) desc; t_stat r; -struct InstHistory *h; +InstHistory *h; extern char *opcode[]; -if (hst_lnt == 0) return SCPE_NOFNC; /* enabled? */ +if (hst_lnt == 0) return SCPE_NOFNC; /* enabled? */ if (cptr) { - lnt = (int32) get_uint (cptr, 10, hst_lnt, &r); - if ((r != SCPE_OK) || (lnt == 0)) return SCPE_ARG; } + lnt = (int32) get_uint (cptr, 10, hst_lnt, &r); + if ((r != SCPE_OK) || (lnt == 0)) return SCPE_ARG; + } else lnt = hst_lnt; -di = hst_p - lnt; /* work forward */ +di = hst_p - lnt; /* work forward */ if (di < 0) di = di + hst_lnt; fprintf (st, "PC PSL IR\n\n"); -for (k = 0; k < lnt; k++) { /* print specified */ - h = &hst[(di++) % hst_lnt]; /* 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 & (DR_LNMASK|DR_ACMASK)) { - case RB: case RW: case RL: /* read */ - case AB: case AW: case AL: case AQ: case AO: /* address */ - case MB: case MW: case ML: /* modify */ - fprintf (st, "%X", h->opnd[j++]); - break; - case RQ: case MQ: /* read, modify quad */ - fprintf (st, "%X%08X", h->opnd[j], h->opnd[j + 1]); - j = j + 2; - break; - case RO: case MO: /* read, modify octa */ - fprintf (st, "%X%08X%08X%08X", h->opnd[j], - h->opnd[j + 1], h->opnd[j + 2], h->opnd[j + 3]); - j = j + 4; - break; - case WB: case WW: case WL: case WQ: case WO: /* 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 */ +for (k = 0; k < lnt; k++) { /* print specified */ + h = &hst[(di++) % hst_lnt]; /* 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 & (DR_LNMASK|DR_ACMASK)) { + case RB: case RW: case RL: /* read */ + case AB: case AW: case AL: case AQ: case AO: /* address */ + case MB: case MW: case ML: /* modify */ + fprintf (st, "%X", h->opnd[j++]); + break; + case RQ: case MQ: /* read, modify quad */ + fprintf (st, "%X%08X", h->opnd[j], h->opnd[j + 1]); + j = j + 2; + break; + case RO: case MO: /* read, modify octa */ + fprintf (st, "%X%08X%08X%08X", h->opnd[j], + h->opnd[j + 1], h->opnd[j + 2], h->opnd[j + 3]); + j = j + 4; + break; + case WB: case WW: case WL: case WQ: case WO: /* 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 index 4bee2e8e..44fe9687 100644 --- a/VAX/vax_cpu1.c +++ b/VAX/vax_cpu1.c @@ -1,6 +1,6 @@ /* vax_cpu1.c: VAX complex instructions - Copyright (c) 1998-2004, Robert M Supnik + Copyright (c) 1998-2005, 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"), @@ -19,59 +19,59 @@ 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 + 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-Sep-04 RMS Added conditionals for full VAX - Moved emulation to vax_cis.c - Moved model-specific IPRs to system module - 27-Jan-04 RMS Added device logging support - Fixed EXTxV, INSV double register PC reference fault - 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) + 30-Sep-04 RMS Added conditionals for full VAX + Moved emulation to vax_cis.c + Moved model-specific IPRs to system module + 27-Jan-04 RMS Added device logging support + Fixed EXTxV, INSV double register PC reference fault + 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 + - 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 + - CALLS, CALLG, RET + - PUSHR, POPR Queue instructions: - - INSQUE, REMQUE - - INSQHI, INSQTI, REMQHI, REMQTI + - INSQUE, REMQUE + - INSQHI, INSQTI, REMQHI, REMQTI String instructions: - - MOVC3, MOVC5, CMPC3, CMPC5 - - LOCC, SKPC, SCANC, SPANC + - 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) + - CHMK, CHME, CHMS, CHMU + - PROBER, PROBEW, REI + - MTPR, MFPR + - LDPCTX, SVPCTX + - (interrupt and exception routine) */ - + #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 */ + 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; @@ -109,13 +109,13 @@ extern int32 ReadIPR (int32 rg); extern void WriteIPR (int32 rg, int32 val); extern t_bool BadCmPSL (int32 newpsl); 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 + opnd[0] = position (pos.rl) + opnd[1] = register number/memory flag + opnd[2] = memory address, if memory Returns bit to be tested */ @@ -125,13 +125,14 @@ 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 */ +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) @@ -140,26 +141,27 @@ 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 */ +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 + 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 */ @@ -172,29 +174,32 @@ 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 + size) > 32) && (rn >= nSP)) /* span 2 reg, PC? */ - RSVD_ADDR_FAULT; /* 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)); } +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 + size) > 32) && (rn >= nSP)) /* span 2 reg, PC? */ + RSVD_ADDR_FAULT; /* 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 + 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 */ @@ -207,30 +212,35 @@ 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_ADDR_FAULT; /* if PC, fault */ - mask = byte_mask[pos + size - 32]; /* insert fragment */ - val = ins >> (32 - pos); - R[rn + 1] = (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); } +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_ADDR_FAULT; /* if PC, fault */ + mask = byte_mask[pos + size - 32]; /* insert fragment */ + val = ins >> (32 - pos); + R[rn + 1] = (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; } @@ -243,84 +253,87 @@ 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; } + +#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 + 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: + 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) | - +---------------+-----------------------------------------------+ + +---------------------------------------------------------------+ + | 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). + 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: + 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 | - +--+--+-----+----------------------------------+ + 15 14 13 12 11 0 + +--+--+-----+----------------------------------+ + |DV|IV| MBZ | register mask | + +--+--+-----+----------------------------------+ - CALLG/CALLS operation: + 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 + 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) @@ -328,16 +341,17 @@ 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 */ +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 */ +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 */ + 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); @@ -348,21 +362,21 @@ 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 */ +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 */ + ((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 */ +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) @@ -370,17 +384,17 @@ 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 */ +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 */ + 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); @@ -391,16 +405,17 @@ 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 */ +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) @@ -410,11 +425,11 @@ 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 */ + ((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); @@ -428,7 +443,7 @@ PUSHR_PUSH (3); PUSHR_PUSH (2); PUSHR_PUSH (1); PUSHR_PUSH (0); -SP = tsp; /* update stk ptr */ +SP = tsp; /* update stk ptr */ return; } @@ -439,10 +454,10 @@ 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 */ + ((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); @@ -455,30 +470,30 @@ 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 */ +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) + 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 + BEFORE AFTER - P: S P: E W - P+4: (n/a) P+4: (n/a) + P: S P: E W + P+4: (n/a) P+4: (n/a) - E: --- E: S W - E+4: --- E+4: P W + E: --- E: S W + E+4: --- E+4: P W - S: (n/a) S: (n/a) - S+4: P S+4: E 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. @@ -490,37 +505,37 @@ 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 */ +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) + 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 + BEFORE AFTER - P: E P: S W - P+4: (n/a) P+4: (n/a) + 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 + 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 + S: (n/a) S: (n/a) + S+4: E W S+4: P */ @@ -529,48 +544,49 @@ 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 */ +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) + opnd[0] = entry (ent.ab) + opnd[1] = header (hdr.aq) - Pictorially: + Pictorially: - BEFORE AFTER INSQHI AFTER INSQTI + 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 + 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 + 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 + 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 + 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 + 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. + 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) @@ -579,19 +595,19 @@ 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 */ +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) @@ -600,50 +616,51 @@ 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 */ +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) + opnd[0] = header (hdr.aq) + opnd[1:2] = destination address (dst.al) - Pictorially: + Pictorially: - BEFORE AFTER REMQHI AFTER REMQTI + 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 + 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 + 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 + 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 + 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. + 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) @@ -651,30 +668,33 @@ 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 */ +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 */ +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) @@ -682,70 +702,75 @@ 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 */ +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 */ +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 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 /* MOVC3, MOVC5 if PSL = 0 and MOVC3, - opnd[0] = length - opnd[1] = source address - opnd[2] = dest address + 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 + 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 + 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) @@ -754,240 +779,275 @@ 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 */ +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 + 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--) { - 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--) { - 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--) { - 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 */ +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--) { + 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--) { + 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--) { + 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 + 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 + 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 + 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 */ +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 (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 */ + 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 + opnd[0] = match character + opnd[1] = source length + opnd[2] = source address if PSL = 1, - R0 = delta-PC/match/source length - R1 = source address + 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 */ - 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 */ +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 */ + 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 + 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 + 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 */ - 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; } +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 */ + 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[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 + 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) @@ -999,37 +1059,41 @@ 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 */ +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); + (oldcur << PSL_V_PRV); if (DEBUG_PRI (cpu_dev, LOG_CPU_I)) fprintf (sim_deb, - ">>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 */ + ">>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 + opnd[0] = operand */ int32 op_chm (int32 *opnd, int32 cc, int32 opc) @@ -1040,46 +1104,48 @@ 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 (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); + 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 */ +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 +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 PSL - 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 - 9 tmp<31> = 1 => tmp = 3, tmp = 3>, tmp = 0 +Rule SRM formulation Comment +---- --------------- ------- + 1 tmp<25:24> GEQ PSL<25:24> tmp GEQ PSL + 2 tmp<26> LEQ PSL<26> tmp LEQ PSL + 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 + 9 tmp<31> = 1 => tmp = 3, tmp = 3>, tmp = 0 */ int32 op_rei (int32 acc) @@ -1090,53 +1156,58 @@ int32 newcur = PSL_GETCUR (newpsl); int32 oldcur = PSL_GETCUR (PSL); int32 newipl, i; -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 */ -if (newpsl & PSL_CM) { /* setting cmode? */ - if (BadCmPSL (newpsl)) RSVD_OPND_FAULT; /* validate PSL */ - for (i = 0; i < 7; i++) R[i] = R[i] & WMASK; /* mask R0-R6, PC */ - newpc = newpc & WMASK; } -SP = SP + 8; /* pop stack */ -if (PSL & PSL_IS) IS = SP; /* save stack */ +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 */ +if (newpsl & PSL_CM) { /* setting cmode? */ + if (BadCmPSL (newpsl)) RSVD_OPND_FAULT; /* validate PSL */ + for (i = 0; i < 7; i++) R[i] = R[i] & WMASK; /* mask R0-R6, PC */ + newpc = newpc & WMASK; + } +SP = SP + 8; /* pop stack */ +if (PSL & PSL_IS) IS = SP; /* save stack */ else STK[oldcur] = SP; if (DEBUG_PRI (cpu_dev, LOG_CPU_R)) fprintf (sim_deb, - ">>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 (DEBUG_PRI (cpu_dev, LOG_CPU_R)) fprintf (sim_deb, - ">>REI: AST delivered\n"); - SISR = SISR | SISR_2; } } -JUMP (newpc); /* set new PC */ -return newpsl & CC_MASK; /* set new cc */ + ">>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 (DEBUG_PRI (cpu_dev, LOG_CPU_R)) fprintf (sim_deb, + ">>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 */ +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[0] = ReadLP (pcbpa + 16); /* restore registers */ R[1] = ReadLP (pcbpa + 20); R[2] = ReadLP (pcbpa + 24); R[3] = ReadLP (pcbpa + 28); @@ -1150,27 +1221,27 @@ 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 */ +newpc = ReadLP (pcbpa + 72); /* get PC, PSL */ newpsl = ReadLP (pcbpa + 76); -P0BR = ReadLP (pcbpa + 80); /* restore mem mgt */ +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 */ -pme = (P1LR >> 31) & 1; /* restore PME */ +ASTLVL = (P0LR >> 24) & AST_MASK; /* restore AST */ +pme = (P1LR >> 31) & 1; /* restore PME */ P0BR = P0BR & BR_MASK; P0LR = P0LR & LR_MASK; P1BR = P1BR & BR_MASK; P1LR = P1LR & LR_MASK; -zap_tb (0); /* clear process TB */ +zap_tb (0); /* clear process TB */ set_map_reg (); if (DEBUG_PRI (cpu_dev, LOG_CPU_P)) fprintf (sim_deb, - ">>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 */ + ">>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, newpc, L_LONG, WA); /* push PC, PSL */ Write (SP + 4, newpsl, L_LONG, WA); return; } @@ -1181,23 +1252,25 @@ 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 */ +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 (DEBUG_PRI (cpu_dev, LOG_CPU_P)) fprintf (sim_deb, - ">>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 */ + ">>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, 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 + 16, R[0]); /* save registers */ WriteLP (pcbpa + 20, R[1]); WriteLP (pcbpa + 24, R[2]); WriteLP (pcbpa + 28, R[3]); @@ -1211,56 +1284,65 @@ 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 + 72, savpc); /* save PC, PSL */ WriteLP (pcbpa + 76, savpsl); return; } - + /* PROBER and PROBEW - opnd[0] = mode - opnd[1] = length - opnd[2] = base address + 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 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 */ +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 + opnd[0] = data + opnd[1] = register number */ int32 op_mtpr (int32 *opnd) @@ -1269,154 +1351,196 @@ 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_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_TBCHK: /* TBCHK */ - if (chk_tb_ent (val)) cc = cc | CC_V; - break; -case MT_PME: /* PME */ - pme = val & 1; - break; -default: - WriteIPR (prn, val); /* others */ - break; } +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_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_TBCHK: /* TBCHK */ + if (chk_tb_ent (val)) cc = cc | CC_V; + break; + + case MT_PME: /* PME */ + pme = val & 1; + 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_MAPEN: /* MAPEN */ - val = mapen & 1; - break; -case MT_PME: - val = pme & 1; - 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; } +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_MAPEN: /* MAPEN */ + val = mapen & 1; + break; + + case MT_PME: + val = pme & 1; + 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; } diff --git a/VAX/vax_defs.h b/VAX/vax_defs.h index bf2d871a..df38dba4 100644 --- a/VAX/vax_defs.h +++ b/VAX/vax_defs.h @@ -1,6 +1,6 @@ /* vax_defs.h: VAX architecture definitions file - Copyright (c) 1998-2004, Robert M Supnik + Copyright (c) 1998-2005, 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"), @@ -19,27 +19,28 @@ 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 + 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 - 02-Sep-04 RMS Added octa specifier definitions - 30-Aug-04 RMS Added octa, h_floating instruction definitions - 24-Aug-04 RMS Added compatibility mode definitions - 18-Apr-04 RMS Added octa, fp, string definitions - 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 + 22-Jul-05 RMS Fixed warning from Solaris C (from Doug Gwyn) + 02-Sep-04 RMS Added octa specifier definitions + 30-Aug-04 RMS Added octa, h_floating instruction definitions + 24-Aug-04 RMS Added compatibility mode definitions + 18-Apr-04 RMS Added octa, fp, string definitions + 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 +#define _VAX_DEFS_H 0 #ifndef VM_VAX -#define VM_VAX 0 +#define VM_VAX 0 #endif #include "sim_defs.h" @@ -47,469 +48,469 @@ /* 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_CMODE (-SCB_CMODE) /* comp mode fault */ -#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 CMODE_FAULT(cd) p1 = (cd), ABORT (ABORT_CMODE) -#define MACH_CHECK(cd) p1 = (cd), ABORT (ABORT_MCHK) +#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_CMODE (-SCB_CMODE) /* comp mode fault */ +#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 CMODE_FAULT(cd) p1 = (cd), ABORT (ABORT_CMODE) +#define MACH_CHECK(cd) p1 = (cd), ABORT (ABORT_MCHK) /* Recovery queue */ -#define RQ_RN 0xF /* register */ -#define RQ_V_LNT 4 /* length */ -#define RQ_M_LNT 0x7 /* 0,1,2,3,4 */ -#define RQ_DIR 0x800 /* 0 = -, 1 = + */ -#define RQ_REC(d,r) (((d) << RQ_V_LNT) | (r)) -#define RQ_GETRN(x) ((x) & RQ_RN) -#define RQ_GETLNT(x) (((x) >> RQ_V_LNT) & RQ_M_LNT) +#define RQ_RN 0xF /* register */ +#define RQ_V_LNT 4 /* length */ +#define RQ_M_LNT 0x7 /* 0,1,2,3,4 */ +#define RQ_DIR 0x800 /* 0 = -, 1 = + */ +#define RQ_REC(d,r) (((d) << RQ_V_LNT) | (r)) +#define RQ_GETRN(x) ((x) & RQ_RN) +#define RQ_GETLNT(x) (((x) >> RQ_V_LNT) & RQ_M_LNT) /* 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 */ +#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 L_OCTA 16 -#define NUM_INST 512 /* one byte+two byte */ -#define MAX_SPEC 6 /* max spec/instr */ +#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 L_OCTA 16 +#define NUM_INST 512 /* one byte+two byte */ +#define MAX_SPEC 6 /* max spec/instr */ /* Floating point formats */ -#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 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) +#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) -#define H_V_EXP 0 /* h exponent */ -#define H_M_EXP 0x7FFF -#define H_BIAS 0x4000 /* h bias */ -#define H_EXP (H_M_EXP << H_V_EXP) -#define H_HB (1 << H_V_EXP) /* h hidden bit */ -#define H_GUARD (15 - H_V_EXP) /* # guard bits */ -#define H_GETEXP(x) (((x) >> H_V_EXP) & H_M_EXP) +#define H_V_EXP 0 /* h exponent */ +#define H_M_EXP 0x7FFF +#define H_BIAS 0x4000 /* h bias */ +#define H_EXP (H_M_EXP << H_V_EXP) +#define H_HB (1 << H_V_EXP) /* h hidden bit */ +#define H_GUARD (15 - H_V_EXP) /* # guard bits */ +#define H_GETEXP(x) (((x) >> H_V_EXP) & H_M_EXP) /* Memory management modes */ -#define KERN 0 -#define EXEC 1 -#define SUPV 2 -#define USER 3 +#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 KSP STK[KERN] -#define ESP STK[EXEC] -#define SSP STK[SUPV] -#define USP STK[USER] -#define IS STK[4] +#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 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_CM 31 /* compatibility mode */ -#define PSL_CM (1 << PSL_V_CM) -#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_PRV) -#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 (0x30200000 | 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) +#define PSL_V_CM 31 /* compatibility mode */ +#define PSL_CM (1u << PSL_V_CM) +#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_PRV) +#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 (0x30200000 | 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) +#define SISR_MASK 0xFFFE +#define SISR_2 (1 << 2) /* AST register */ -#define AST_MASK 7 -#define AST_MAX 4 +#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) +#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) +#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) +#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_FLTOVF (3 << TIR_V_TRAP) /* flt overflow */ -#define TRAP_FLTDIV (4 << TIR_V_TRAP) /* flt/dec div by zero */ -#define TRAP_FLTUND (5 << TIR_V_TRAP) /* flt underflow */ -#define TRAP_DECOVF (6 << TIR_V_TRAP) /* decimal overflow */ -#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) +#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_FLTOVF (3 << TIR_V_TRAP) /* flt overflow */ +#define TRAP_FLTDIV (4 << TIR_V_TRAP) /* flt/dec div by zero */ +#define TRAP_FLTUND (5 << TIR_V_TRAP) /* flt underflow */ +#define TRAP_DECOVF (6 << TIR_V_TRAP) /* decimal overflow */ +#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 */ +#define FLT_OVRFLO 0x8 /* flt overflow */ +#define FLT_DIVZRO 0x9 /* flt div by zero */ +#define FLT_UNDFLO 0xA /* flt underflow */ /* Compatability mode fault parameters */ -#define CMODE_RSVI 0x0 /* reserved instr */ -#define CMODE_BPT 0x1 /* BPT */ -#define CMODE_IOT 0x2 /* IOT */ -#define CMODE_EMT 0x3 /* EMT */ -#define CMODE_TRAP 0x4 /* TRAP */ -#define CMODE_ILLI 0x5 /* illegal instr */ -#define CMODE_ODD 0x6 /* odd address */ +#define CMODE_RSVI 0x0 /* reserved instr */ +#define CMODE_BPT 0x1 /* BPT */ +#define CMODE_IOT 0x2 /* IOT */ +#define CMODE_EMT 0x3 /* EMT */ +#define CMODE_TRAP 0x4 /* TRAP */ +#define CMODE_ILLI 0x5 /* illegal instr */ +#define CMODE_ODD 0x6 /* odd address */ /* EDITPC suboperators */ -#define EO_END 0x00 /* end */ -#define EO_END_FLOAT 0x01 /* end float */ -#define EO_CLR_SIGNIF 0x02 /* clear signif */ -#define EO_SET_SIGNIF 0x03 /* set signif */ -#define EO_STORE_SIGN 0x04 /* store sign */ -#define EO_LOAD_FILL 0x40 /* load fill */ -#define EO_LOAD_SIGN 0x41 /* load sign */ -#define EO_LOAD_PLUS 0x42 /* load sign if + */ -#define EO_LOAD_MINUS 0x43 /* load sign if - */ -#define EO_INSERT 0x44 /* insert */ -#define EO_BLANK_ZERO 0x45 /* blank zero */ -#define EO_REPL_SIGN 0x46 /* replace sign */ -#define EO_ADJUST_LNT 0x47 /* adjust length */ -#define EO_FILL 0x80 /* fill */ -#define EO_MOVE 0x90 /* move */ -#define EO_FLOAT 0xA0 /* float */ -#define EO_RPT_MASK 0x0F /* rpt mask */ -#define EO_RPT_FLAG 0x80 /* rpt flag */ +#define EO_END 0x00 /* end */ +#define EO_END_FLOAT 0x01 /* end float */ +#define EO_CLR_SIGNIF 0x02 /* clear signif */ +#define EO_SET_SIGNIF 0x03 /* set signif */ +#define EO_STORE_SIGN 0x04 /* store sign */ +#define EO_LOAD_FILL 0x40 /* load fill */ +#define EO_LOAD_SIGN 0x41 /* load sign */ +#define EO_LOAD_PLUS 0x42 /* load sign if + */ +#define EO_LOAD_MINUS 0x43 /* load sign if - */ +#define EO_INSERT 0x44 /* insert */ +#define EO_BLANK_ZERO 0x45 /* blank zero */ +#define EO_REPL_SIGN 0x46 /* replace sign */ +#define EO_ADJUST_LNT 0x47 /* adjust length */ +#define EO_FILL 0x80 /* fill */ +#define EO_MOVE 0x90 /* move */ +#define EO_FLOAT 0xA0 /* float */ +#define EO_RPT_MASK 0x0F /* rpt mask */ +#define EO_RPT_FLAG 0x80 /* rpt flag */ /* EDITPC R2 packup parameters */ -#define ED_V_SIGN 8 /* sign */ -#define ED_M_SIGN 0xFF -#define ED_SIGN (ED_M_SIGN << ED_V_SIGN) -#define ED_V_FILL 0 /* fill */ -#define ED_M_FILL 0xFF -#define ED_FILL (ED_M_FILL << ED_V_FILL) -#define ED_GETSIGN(x) (((x) >> ED_V_SIGN) & ED_M_SIGN) -#define ED_GETFILL(x) (((x) >> ED_V_FILL) & ED_M_FILL) -#define ED_PUTSIGN(r,x) (((r) & ~ED_SIGN) | (((x) << ED_V_SIGN) & ED_SIGN)) -#define ED_PUTFILL(r,x) (((r) & ~ED_FILL) | (((x) << ED_V_FILL) & ED_FILL)) +#define ED_V_SIGN 8 /* sign */ +#define ED_M_SIGN 0xFF +#define ED_SIGN (ED_M_SIGN << ED_V_SIGN) +#define ED_V_FILL 0 /* fill */ +#define ED_M_FILL 0xFF +#define ED_FILL (ED_M_FILL << ED_V_FILL) +#define ED_GETSIGN(x) (((x) >> ED_V_SIGN) & ED_M_SIGN) +#define ED_GETFILL(x) (((x) >> ED_V_FILL) & ED_M_FILL) +#define ED_PUTSIGN(r,x) (((r) & ~ED_SIGN) | (((x) << ED_V_SIGN) & ED_SIGN)) +#define ED_PUTFILL(r,x) (((r) & ~ED_FILL) | (((x) << ED_V_FILL) & ED_FILL)) /* 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_CMODE 0x30 /* comp mode fault */ -#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 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_CMODE 0x30 /* comp mode fault */ +#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 */ +#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 */ +#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_V_USPMASK 4 -#define DR_M_USPMASK 0x70 /* #spec, sym_ */ -#define DR_GETNSP(x) ((x) & DR_NSPMASK) -#define DR_GETUSP(x) (((x) >> DR_V_USPMASK) & DR_M_USPMASK) +#define DR_F 0x80 /* FPD ok flag */ +#define DR_NSPMASK 0x07 /* #specifiers */ +#define DR_V_USPMASK 4 +#define DR_M_USPMASK 0x70 /* #spec, sym_ */ +#define DR_GETNSP(x) ((x) & DR_NSPMASK) +#define DR_GETUSP(x) (((x) >> DR_V_USPMASK) & DR_M_USPMASK) /* Decode ROM: specifier entry */ -#define DR_ACMASK 0x300 /* type */ -#define DR_SPFLAG 0x008 /* special decode */ -#define DR_LNMASK 0x007 /* length mask */ -#define DR_LNT(x) (1 << (x & DR_LNMASK)) /* disp to lnt */ +#define DR_ACMASK 0x300 /* type */ +#define DR_SPFLAG 0x008 /* special decode */ +#define DR_LNMASK 0x007 /* length mask */ +#define DR_LNT(x) (1 << (x & DR_LNMASK)) /* disp to lnt */ /* Decode ROM: length */ -#define DR_BYTE 0x000 /* byte */ -#define DR_WORD 0x001 /* word */ -#define DR_LONG 0x002 /* long */ -#define DR_QUAD 0x003 /* quad */ -#define DR_OCTA 0x004 /* octa */ +#define DR_BYTE 0x000 /* byte */ +#define DR_WORD 0x001 /* word */ +#define DR_LONG 0x002 /* long */ +#define DR_QUAD 0x003 /* quad */ +#define DR_OCTA 0x004 /* octa */ /* Decode ROM: operand type */ -#define SH0 0x000 /* short literal */ -#define SH1 0x010 -#define SH2 0x020 -#define SH3 0x030 -#define IDX 0x040 /* indexed */ -#define GRN 0x050 /* register */ -#define RGD 0x060 /* register def */ -#define ADC 0x070 /* autodecrement */ -#define AIN 0x080 /* autoincrement */ -#define AID 0x090 /* autoinc def */ -#define BDP 0x0A0 /* byte disp */ -#define BDD 0x0B0 /* byte disp def */ -#define WDP 0x0C0 /* word disp */ -#define WDD 0x0D0 /* word disp def */ -#define LDP 0x0E0 /* long disp */ -#define LDD 0x0F0 /* long disp def */ +#define SH0 0x000 /* short literal */ +#define SH1 0x010 +#define SH2 0x020 +#define SH3 0x030 +#define IDX 0x040 /* indexed */ +#define GRN 0x050 /* register */ +#define RGD 0x060 /* register def */ +#define ADC 0x070 /* autodecrement */ +#define AIN 0x080 /* autoincrement */ +#define AID 0x090 /* autoinc def */ +#define BDP 0x0A0 /* byte disp */ +#define BDD 0x0B0 /* byte disp def */ +#define WDP 0x0C0 /* word disp */ +#define WDD 0x0D0 /* word disp def */ +#define LDP 0x0E0 /* long disp */ +#define LDD 0x0F0 /* long disp def */ /* Decode ROM: access type */ -#define DR_R 0x000 /* read */ -#define DR_M 0x100 /* modify */ -#define DR_A 0x200 /* address */ -#define DR_W 0x300 /* write */ +#define DR_R 0x000 /* read */ +#define DR_M 0x100 /* modify */ +#define DR_A 0x200 /* address */ +#define DR_W 0x300 /* write */ /* Decode ROM: access type and length */ -#define RB (DR_R|DR_BYTE) -#define RW (DR_R|DR_WORD) -#define RL (DR_R|DR_LONG) -#define RQ (DR_R|DR_QUAD) -#define RO (DR_R|DR_OCTA) -#define MB (DR_M|DR_BYTE) -#define MW (DR_M|DR_WORD) -#define ML (DR_M|DR_LONG) -#define MQ (DR_M|DR_QUAD) -#define MO (DR_M|DR_OCTA) -#define AB (DR_A|DR_BYTE) -#define AW (DR_A|DR_WORD) -#define AL (DR_A|DR_LONG) -#define AQ (DR_A|DR_QUAD) -#define AO (DR_A|DR_OCTA) -#define WB (DR_W|DR_BYTE) -#define WW (DR_W|DR_WORD) -#define WL (DR_W|DR_LONG) -#define WQ (DR_W|DR_QUAD) -#define WO (DR_W|DR_OCTA) +#define RB (DR_R|DR_BYTE) +#define RW (DR_R|DR_WORD) +#define RL (DR_R|DR_LONG) +#define RQ (DR_R|DR_QUAD) +#define RO (DR_R|DR_OCTA) +#define MB (DR_M|DR_BYTE) +#define MW (DR_M|DR_WORD) +#define ML (DR_M|DR_LONG) +#define MQ (DR_M|DR_QUAD) +#define MO (DR_M|DR_OCTA) +#define AB (DR_A|DR_BYTE) +#define AW (DR_A|DR_WORD) +#define AL (DR_A|DR_LONG) +#define AQ (DR_A|DR_QUAD) +#define AO (DR_A|DR_OCTA) +#define WB (DR_W|DR_BYTE) +#define WW (DR_W|DR_WORD) +#define WL (DR_W|DR_LONG) +#define WQ (DR_W|DR_QUAD) +#define WO (DR_W|DR_OCTA) /* 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 rq except for short literal - rg = g_floating, treated as rq except for short literal - rh = h_floating, treated as ro except for short literal - bw = branch byte displacement - bw = branch word displacement + 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 rq except for short literal + rg = g_floating, treated as rq except for short literal + rh = h_floating, treated as ro except for short literal + bw = branch byte displacement + bw = branch word displacement The 'underlying' access type and length must be correct for indexing. rg works because rq and mq are treated identically. */ -#define VB (DR_SPFLAG|WB) /* .vb */ -#define RF (DR_SPFLAG|RL) /* .rf */ -#define RD (DR_SPFLAG|RQ) /* .rd */ -#define RG (DR_SPFLAG|MQ) /* .rg */ -#define RH (DR_SPFLAG|RO) /* .rh */ -#define BB (DR_SPFLAG|WB|6) /* byte branch */ -#define BW (DR_SPFLAG|WB|7) /* word branch */ +#define VB (DR_SPFLAG|WB) /* .vb */ +#define RF (DR_SPFLAG|RL) /* .rf */ +#define RD (DR_SPFLAG|RQ) /* .rd */ +#define RG (DR_SPFLAG|MQ) /* .rg */ +#define RH (DR_SPFLAG|RO) /* .rh */ +#define BB (DR_SPFLAG|WB|6) /* byte branch */ +#define BW (DR_SPFLAG|WB|7) /* word branch */ /* 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 */ +#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 */ +#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_NICR 25 -#define MT_ICR 26 -#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_MAPEN 56 -#define MT_TBIA 57 -#define MT_TBIS 58 -#define MT_PME 61 -#define MT_SID 62 -#define MT_TBCHK 63 +#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_NICR 25 +#define MT_ICR 26 +#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_MAPEN 56 +#define MT_TBIA 57 +#define MT_TBIS 58 +#define MT_PME 61 +#define MT_SID 62 +#define MT_TBCHK 63 -#define BR_MASK 0xFFFFFFFC -#define LR_MASK 0x003FFFFF +#define BR_MASK 0xFFFFFFFC +#define LR_MASK 0x003FFFFF /* Opcodes */ @@ -558,152 +559,152 @@ enum opcodes { /* 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) +#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 CMODE_JUMP(d) PCQ_ENTRY, PC = (d) -#define SETPC(d) PC = (d), FLUSH_ISTR -#define FLUSH_ISTR ibcnt = 0, ppc = -1 +#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 CMODE_JUMP(d) PCQ_ENTRY, PC = (d) +#define SETPC(d) PC = (d), FLUSH_ISTR +#define FLUSH_ISTR ibcnt = 0, ppc = -1 /* Character string instructions */ -#define STR_V_DPC 24 /* delta PC */ -#define STR_M_DPC 0xFF -#define STR_V_CHR 16 /* char argument */ -#define STR_M_CHR 0xFF -#define STR_LNMASK 0xFFFF /* string length */ -#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)) +#define STR_V_DPC 24 /* delta PC */ +#define STR_M_DPC 0xFF +#define STR_V_CHR 16 /* char argument */ +#define STR_M_CHR 0xFF +#define STR_LNMASK 0xFFFF /* string length */ +#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)) /* 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 +#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_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 + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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_O(rl,rm2,rm1,rh) \ - if ((rh) & LSIGN) cc = CC_N | (cc & CC_C); \ - else if (((rl) | (rm2) | (rm1) | (rh)) == 0) cc = CC_Z | (cc & CC_C); \ - else cc = cc & CC_C -#define CC_IIZP_FP CC_IIZP_W + if ((rh) & LSIGN) cc = CC_N | (cc & CC_C); \ + else if (((rl) | (rm2) | (rm1) | (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; } + if (((~(s1) ^ (s2)) & ((s1) ^ (r))) & BSIGN) { V_INTOV; } #define V_ADD_W(r,s1,s2) \ - if (((~(s1) ^ (s2)) & ((s1) ^ (r))) & WSIGN) { V_INTOV; } + if (((~(s1) ^ (s2)) & ((s1) ^ (r))) & WSIGN) { V_INTOV; } #define V_ADD_L(r,s1,s2) \ - if (((~(s1) ^ (s2)) & ((s1) ^ (r))) & LSIGN) { V_INTOV; } + if (((~(s1) ^ (s2)) & ((s1) ^ (r))) & LSIGN) { V_INTOV; } #define C_ADD(r,s1,s2) \ - if (((uint32) r) < ((uint32) s2)) cc = cc | CC_C + 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) + 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) + 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) + 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; } + if ((((s1) ^ (s2)) & (~(s1) ^ (r))) & BSIGN) { V_INTOV; } #define V_SUB_W(r,s1,s2) \ - if ((((s1) ^ (s2)) & (~(s1) ^ (r))) & WSIGN) { V_INTOV; } + if ((((s1) ^ (s2)) & (~(s1) ^ (r))) & WSIGN) { V_INTOV; } #define V_SUB_L(r,s1,s2) \ - if ((((s1) ^ (s2)) & (~(s1) ^ (r))) & LSIGN) { V_INTOV; } + if ((((s1) ^ (s2)) & (~(s1) ^ (r))) & LSIGN) { V_INTOV; } #define C_SUB(r,s1,s2) \ - if (((uint32) s2) < ((uint32) s1)) cc = cc | CC_C + 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) + 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) + 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) + 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 + 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 + 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 + 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 */ @@ -713,4 +714,4 @@ enum opcodes { #include "vaxmod_defs.h" #endif -#endif /* _VAX_DEFS_H */ +#endif /* _VAX_DEFS_H */ diff --git a/VAX/vax_doc.txt b/VAX/vax_doc.txt index 9e13d324..e3fff9f5 100644 --- a/VAX/vax_doc.txt +++ b/VAX/vax_doc.txt @@ -1,7 +1,7 @@ To: Users From: Bob Supnik Subj: VAX Simulator Usage -Date: 15-Nov-2004 +Date: 01-Jul-2005 COPYRIGHT NOTICE @@ -27,8 +27,8 @@ The following copyright notice applies to both the SIMH source and binary: 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 + 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. @@ -869,7 +869,7 @@ 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 SET DZ DISCONNECT=linenumber command disconnects the specified line. The DZV11 implements these registers: @@ -953,7 +953,7 @@ a SET VH DISCONNECT command, or a DETACH VH command. The SHOW VH CONNECTIONS command displays the current connections to the VH. The SHOW VH STATISTICS command displays statistics for active connections. -The SET VH DISCONNECT=linenumber disconnects the specified line. +The SET VH DISCONNECT=linenumber command disconnects the specified line. The DHQ11 implements these registers, though not all can be examined from SCP: diff --git a/VAX/vax_fpa.c b/VAX/vax_fpa.c index 1eaa18de..94f564b8 100644 --- a/VAX/vax_fpa.c +++ b/VAX/vax_fpa.c @@ -1,6 +1,6 @@ /* vax_fpa.c - VAX f_, d_, g_floating instructions - Copyright (c) 1998-2004, Robert M Supnik + Copyright (c) 1998-2005, 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"), @@ -19,24 +19,24 @@ 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 + 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-Sep-04 RMS Comment and formating changes based on vax_octa.c - 18-Apr-04 RMS Moved format definitions to vax_defs.h - 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 + 30-Sep-04 RMS Comment and formating changes based on vax_octa.c + 18-Apr-04 RMS Moved format definitions to vax_defs.h + 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 + - 64 bit arithmetic (ASHQ, EMUL, EDIV) + - single precision floating point + - double precision floating point, D and G format */ #include "vax_defs.h" @@ -51,41 +51,40 @@ 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))) +#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 { + int32 sign; + int32 exp; + t_uint64 frac; + } UFP; -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)) +#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); @@ -97,12 +96,12 @@ 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) + 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) @@ -110,20 +109,25 @@ 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) & LMASK); /* hi result */ -return ((int32) (r & LMASK)); /* lo result */ +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) & LMASK); /* hi result */ +return ((int32) (r & LMASK)); /* lo result */ } /* Extended multiply subroutine */ @@ -140,8 +144,8 @@ return ((int32) (lmpy & LMASK)); /* Extended divide - opnd[0] = divisor (non-zero) - opnd[1:2] = dividend + opnd[0] = divisor (non-zero) + opnd[1:2] = dividend */ int32 op_ediv (int32 *opnd, int32 *rh, int32 *flg) @@ -149,24 +153,25 @@ int32 op_ediv (int32 *opnd, int32 *rh, int32 *flg) t_int64 ldvd, ldvr; int32 quo, rem; -*flg = CC_V; /* assume error */ +*flg = CC_V; /* assume error */ *rh = 0; -ldvr = ((opnd[0] & LSIGN)? -opnd[0]: opnd[0]) & LMASK; /* |divisor| */ -ldvd = CONCAT (opnd[2], opnd[1]); /* 64b dividend */ -if (opnd[2] & LSIGN) ldvd = -ldvd; /* |dividend| */ -if (((ldvd >> 32) & LMASK) >= ldvr) return opnd[1]; /* divide work? */ -quo = (int32) (ldvd / ldvr); /* do divide */ +ldvr = ((opnd[0] & LSIGN)? -opnd[0]: opnd[0]) & LMASK; /* |divisor| */ +ldvd = CONCAT (opnd[2], opnd[1]); /* 64b dividend */ +if (opnd[2] & LSIGN) ldvd = -ldvd; /* |dividend| */ +if (((ldvd >> 32) & LMASK) >= 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? */ +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 & LMASK; /* set rem */ -return (quo & LMASK); /* return quo */ +if (opnd[2] & LSIGN) rem = -rem; /* sign of rem */ +*flg = 0; /* no overflow */ +*rh = rem & LMASK; /* set rem */ +return (quo & LMASK); /* return quo */ } - + /* Compare floating */ int32 op_cmpfd (int32 h1, int32 l1, int32 h2, int32 l2) @@ -174,11 +179,13 @@ 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 (h1 & FPSIGN) RSVD_OPND_FAULT; + h1 = l1 = 0; + } if ((h2 & FD_EXP) == 0) { - if (h2 & FPSIGN) RSVD_OPND_FAULT; - h2 = l2 = 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); @@ -191,18 +198,20 @@ 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 (h1 & FPSIGN) RSVD_OPND_FAULT; + h1 = l1 = 0; + } if ((h2 & G_EXP) == 0) { - if (h2 & FPSIGN) RSVD_OPND_FAULT; - h2 = l2 = 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) @@ -210,11 +219,13 @@ int32 op_cvtifdg (int32 val, int32 *rh, int32 opc) UFP a; if (val == 0) { - if (rh) *rh = 0; - return 0; } + if (rh) *rh = 0; + return 0; + } if (val < 0) { - a.sign = FPSIGN; - val = - val; } + 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); @@ -234,23 +245,29 @@ 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; } + 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 */ + 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 ^ LMASK) + 1: a.frac) & LMASK)); } - + /* Extended modularize One of three floating point instructions dropped from the architecture, @@ -264,38 +281,38 @@ int32 op_emodf (int32 *opnd, int32 *intgr, int32 *flg) { UFP a, b; -unpackf (opnd[0], &a); /* unpack operands */ +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, LMASK); /* multiply */ -vax_fmod (&a, FD_BIAS, intgr, flg); /* sep int & frac */ -return rpackfd (&a, NULL); /* return frac */ +a.frac = a.frac | (((t_uint64) opnd[1]) << 32); /* extend src1 */ +vax_fmul (&a, &b, 32, FD_BIAS, LMASK); /* 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[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 */ +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[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 */ +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) @@ -303,32 +320,39 @@ 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 */ +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; } + 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; } @@ -338,57 +362,62 @@ 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) & LMASK; /* split operands */ -bh = (b->frac >> 32) & LMASK; /* into 32b chunks */ -rhi = ah * bh; /* high result */ -if (prec > 32) { /* 64b needed? */ - al = a->frac & LMASK; - bl = b->frac & LMASK; - rmid1 = ah * bl; - rmid2 = al * bh; - rlo = al * bl; - rhi = rhi + ((rmid1 >> 32) & LMASK) + ((rmid2 >> 32) & LMASK); - 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 */ +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) & LMASK; /* split operands */ +bh = (b->frac >> 32) & LMASK; /* into 32b chunks */ +rhi = ah * bh; /* high result */ +if (prec > 32) { /* 64b needed? */ + al = a->frac & LMASK; + bl = b->frac & LMASK; + rmid1 = ah * bl; + rmid2 = al * bh; + rlo = al * bl; + rhi = rhi + ((rmid1 >> 32) & LMASK) + ((rmid2 >> 32) & LMASK); + 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 + 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 */ +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; } @@ -403,33 +432,36 @@ 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 */ +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 */ +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; } +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; @@ -437,27 +469,29 @@ 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 */ +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 */ +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; } @@ -466,78 +500,83 @@ void norm (UFP *r) int32 i; static t_uint64 normmask[5] = { 0xc000000000000000, 0xf000000000000000, 0xff00000000000000, - 0xffff000000000000, 0xffffffff00000000 }; + 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 */ +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 */ +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 */ +*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) & WMASK) << 16) | (((x) >> 16) & WMASK)) +#else /* 32b code */ -struct udp { - uint32 lo; - uint32 hi; -}; +#define WORDSWAP(x) ((((x) & WMASK) << 16) | (((x) >> 16) & WMASK)) -typedef struct udp UDP; +typedef struct { + uint32 lo; + uint32 hi; + } UDP; -struct ufp { - int32 sign; - int32 exp; - struct udp frac; }; +typedef struct { + int32 sign; + int32 exp; + struct udp frac; + } UFP; -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 +#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); @@ -559,12 +598,12 @@ 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) + 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) @@ -572,18 +611,20 @@ int32 op_ashq (int32 *opnd, int32 *rh, int32 *flg) UDP r, sr; uint32 sc = opnd[0]; -r.lo = opnd[1]; /* get source */ +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 */ +*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 */ @@ -591,20 +632,20 @@ return r.lo; /* lo result */ int32 op_emul (int32 mpy, int32 mpc, int32 *rh) { UDP r; -int32 sign = mpy ^ mpc; /* sign of result */ +int32 sign = mpy ^ mpc; /* sign of result */ -if (mpy & LSIGN) mpy = -mpy; /* abs value */ +if (mpy & LSIGN) mpy = -mpy; /* abs value */ if (mpc & LSIGN) mpc = -mpc; -dp_imul (mpy & LMASK, mpc & LMASK, &r); /* 32b * 32b -> 64b */ -if (sign & LSIGN) dp_neg (&r); /* negative result? */ +dp_imul (mpy & LMASK, mpc & LMASK, &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 + opnd[0] = divisor (non-zero) + opnd[1:2] = dividend */ int32 op_ediv (int32 *opnd, int32 *rh, int32 *flg) @@ -612,30 +653,33 @@ 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 */ +dvr = opnd[0]; /* get divisor */ +dvd.lo = opnd[1]; /* get dividend */ dvd.hi = opnd[2]; -*flg = CC_V; /* assume error */ +*flg = CC_V; /* assume error */ *rh = 0; -if (dvd.hi & LSIGN) dp_neg (&dvd); /* |dividend| */ -if (dvr & LSIGN) dvr = NEG (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) & LMASK; /* subtract dvr */ - quo = quo + 1; } } -if ((opnd[0] ^ opnd[2]) & LSIGN) { /* result -? */ - quo = NEG (quo); /* negate */ - if (quo && ((quo & LSIGN) == 0)) return opnd[1]; } /* right sign? */ +if (dvd.hi & LSIGN) dp_neg (&dvd); /* |dividend| */ +if (dvr & LSIGN) dvr = NEG (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) & LMASK; /* subtract dvr */ + quo = quo + 1; + } + } +if ((opnd[0] ^ opnd[2]) & LSIGN) { /* result -? */ + quo = NEG (quo); /* negate */ + if (quo && ((quo & LSIGN) == 0)) return opnd[1]; /* right sign? */ + } else if (quo & LSIGN) return opnd[1]; -if (opnd[2] & LSIGN) *rh = NEG (dvd.hi); /* sign of rem */ +if (opnd[2] & LSIGN) *rh = NEG (dvd.hi); /* sign of rem */ else *rh = dvd.hi; -*flg = 0; /* no overflow */ -return quo; /* return quo */ +*flg = 0; /* no overflow */ +return quo; /* return quo */ } - + /* Compare floating */ int32 op_cmpfd (int32 h1, int32 l1, int32 h2, int32 l2) @@ -667,25 +711,27 @@ 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 & LMASK; /* fraction */ +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 & LMASK; /* fraction */ a.frac.lo = 0; -norm (&a); /* normalize */ -if (opc & 0x100) return rpackg (&a, rh); /* pack and return */ +norm (&a); /* normalize */ +if (opc & 0x100) return rpackg (&a, rh); /* pack and return */ return rpackfd (&a, rh); } @@ -699,25 +745,31 @@ 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? NEG (a.frac.lo): a.frac.lo); /* return lo frac */ +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? NEG (a.frac.lo): a.frac.lo); /* return lo frac */ } - + /* Extended modularize One of three floating point instructions dropped from the architecture, @@ -731,38 +783,38 @@ int32 op_emodf (int32 *opnd, int32 *intgr, int32 *flg) { UFP a, b; -unpackf (opnd[0], &a); /* unpack operands */ +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, LMASK); /* multiply */ -vax_fmod (&a, FD_BIAS, intgr, flg); /* sep int & frac */ -return rpackfd (&a, NULL); /* return frac */ +a.frac.hi = a.frac.hi | opnd[1]; /* extend src1 */ +vax_fmul (&a, &b, 32, FD_BIAS, LMASK); /* 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[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 */ +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[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 */ +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 */ @@ -772,31 +824,38 @@ 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 */ +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 */ + 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; } @@ -820,64 +879,69 @@ 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) & LMASK; /* add hi cross */ - if (rhi.lo < rmid1.hi) /* to low high res */ - rhi.hi = (rhi.hi + 1) & LMASK; - rhi.lo = (rhi.lo + rmid2.hi) & LMASK; - if (rhi.lo < rmid2.hi) - rhi.hi = (rhi.hi + 1) & LMASK; - rlo.hi = (rlo.hi + rmid1.lo) & LMASK; /* add mid1 to low res */ - if (rlo.hi < rmid1.lo) dp_inc (&rhi); /* carry? incr high res */ - rlo.hi = (rlo.hi + rmid2.lo) & LMASK; /* 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 */ +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) & LMASK; /* add hi cross */ + if (rhi.lo < rmid1.hi) /* to low high res */ + rhi.hi = (rhi.hi + 1) & LMASK; + rhi.lo = (rhi.lo + rmid2.hi) & LMASK; + if (rhi.lo < rmid2.hi) + rhi.hi = (rhi.hi + 1) & LMASK; + rlo.hi = (rlo.hi + rmid1.lo) & LMASK; /* add mid1 to low res */ + if (rlo.hi < rmid1.lo) dp_inc (&rhi); /* carry? incr high res */ + rlo.hi = (rlo.hi + rmid2.lo) & LMASK; /* 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 */ +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 + 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 */ +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; } @@ -892,92 +956,100 @@ 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 */ +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 */ +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 */ +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; /* 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; /* hi =, compare lo */ if (a->lo > b->lo) return +1; -return 0; /* hi, lo equal */ +return 0; /* hi, lo equal */ } void dp_add (UDP *a, UDP *b) { -a->lo = (a->lo + b->lo) & LMASK; /* add lo */ -if (a->lo < b->lo) a->hi = a->hi + 1; /* carry? */ -a->hi = (a->hi + b->hi) & LMASK; /* add hi */ +a->lo = (a->lo + b->lo) & LMASK; /* add lo */ +if (a->lo < b->lo) a->hi = a->hi + 1; /* carry? */ +a->hi = (a->hi + b->hi) & LMASK; /* add hi */ return; } void dp_inc (UDP *a) { -a->lo = (a->lo + 1) & LMASK; /* inc lo */ -if (a->lo == 0) a->hi = (a->hi + 1) & LMASK; /* carry? inc hi */ +a->lo = (a->lo + 1) & LMASK; /* inc lo */ +if (a->lo == 0) a->hi = (a->hi + 1) & LMASK; /* 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) & LMASK; /* sub lo */ -a->hi = (a->hi - b->hi) & LMASK; /* sub hi */ +if (a->lo < b->lo) a->hi = a->hi - 1; /* borrow? decr hi */ +a->lo = (a->lo - b->lo) & LMASK; /* sub lo */ +a->hi = (a->hi - b->hi) & LMASK; /* 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)) & LMASK; - r->lo = 0; } +if (sc > 63) r->hi = r->lo = 0; /* > 63? result 0 */ +else if (sc > 31) { /* [32,63]? */ + r->hi = (r->lo << (sc - 32)) & LMASK; + r->lo = 0; + } else if (sc != 0) { - r->hi = ((r->hi << sc) | (r->lo >> (32 - sc))) & LMASK; - r->lo = (r->lo << sc) & LMASK; } + r->hi = ((r->hi << sc) | (r->lo >> (32 - sc))) & LMASK; + r->lo = (r->lo << sc) & LMASK; + } 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)) & LMASK; - r->hi = 0; } +if (sc > 63) r->hi = r->lo = 0; /* > 63? result 0 */ +else if (sc > 31) { /* [32,63]? */ + r->lo = (r->hi >> (sc - 32)) & LMASK; + r->hi = 0; + } else if (sc != 0) { - r->lo = ((r->lo >> sc) | (r->hi << (32 - sc))) & LMASK; - r->hi = (r->hi >> sc) & LMASK; } + r->lo = ((r->lo >> sc) | (r->hi << (32 - sc))) & LMASK; + r->hi = (r->hi >> sc) & LMASK; + } 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 = LMASK; /* > 63? result -1 */ - else { - UDP ones = { LMASK, LMASK }; - dp_lsh (&ones, 64 - sc); /* shift ones */ - r->hi = r->hi | ones.hi; /* or into result */ - r->lo = r->lo | ones.lo; } } +dp_rsh (r, sc); /* do unsigned right */ +if (neg && sc) { /* negative? */ + if (sc > 63) r->hi = r->lo = LMASK; /* > 63? result -1 */ + else { + UDP ones = { LMASK, LMASK }; + dp_lsh (&ones, 64 - sc); /* shift ones */ + r->hi = r->hi | ones.hi; /* or into result */ + r->lo = r->lo | ones.lo; + } + } return; } @@ -985,23 +1057,24 @@ 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) & WMASK; /* split operands */ -bh = (b >> 16) & WMASK; /* into 16b chunks */ +if ((a == 0) || (b == 0)) { /* zero argument? */ + r->hi = r->lo = 0; /* result is zero */ + return; + } +ah = (a >> 16) & WMASK; /* split operands */ +bh = (b >> 16) & WMASK; /* into 16b chunks */ al = a & WMASK; bl = b & WMASK; -rhi = ah * bh; /* high result */ +rhi = ah * bh; /* high result */ rmid1 = ah * bl; rmid2 = al * bh; rlo = al * bl; rhi = rhi + ((rmid1 >> 16) & WMASK) + ((rmid2 >> 16) & WMASK); -rmid1 = (rlo + (rmid1 << 16)) & LMASK; /* add mid1 to lo */ -if (rmid1 < rlo) rhi = rhi + 1; /* carry? incr hi */ -rmid2 = (rmid1 + (rmid2 << 16)) & LMASK; /* add mid2 to to */ -if (rmid2 < rmid1) rhi = rhi + 1; /* carry? incr hi */ -r->hi = rhi & LMASK; /* mask result */ +rmid1 = (rlo + (rmid1 << 16)) & LMASK; /* add mid1 to lo */ +if (rmid1 < rlo) rhi = rhi + 1; /* carry? incr hi */ +rmid2 = (rmid1 + (rmid2 << 16)) & LMASK; /* add mid2 to to */ +if (rmid2 < rmid1) rhi = rhi + 1; /* carry? incr hi */ +r->hi = rhi & LMASK; /* mask result */ r->lo = rmid2; return; } @@ -1012,17 +1085,18 @@ r->lo = NEG (r->lo); r->hi = (~r->hi + (r->lo == 0)) & LMASK; 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->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); @@ -1031,12 +1105,13 @@ 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->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); @@ -1045,12 +1120,13 @@ 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->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); @@ -1061,17 +1137,21 @@ void norm (UFP *r) { int32 i; static uint32 normmask[5] = { - 0xc0000000, 0xf0000000, 0xff000000, 0xffff0000, 0xffffffff }; + 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 */ +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; } @@ -1080,45 +1160,49 @@ 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 */ +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 */ +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)); + (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 */ +*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)); + (WORDSWAP (r->frac.hi) & ~(G_HB | FPSIGN | G_EXP)); } #endif - + /* Floating point instructions */ /* Move/test/move negated floating @@ -1154,7 +1238,7 @@ 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) @@ -1182,17 +1266,17 @@ 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[0], &a); /* F format */ unpackf (opnd[1], &b); -if (sub) a.sign = a.sign ^ FPSIGN; /* sub? -s1 */ -vax_fadd (&a, &b, 0); /* add fractions */ +if (sub) a.sign = a.sign ^ FPSIGN; /* sub? -s1 */ +vax_fadd (&a, &b, 0); /* add fractions */ return rpackfd (&a, NULL); } @@ -1202,8 +1286,8 @@ 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 */ +if (sub) a.sign = a.sign ^ FPSIGN; /* sub? -s1 */ +vax_fadd (&a, &b, 0); /* add fractions */ return rpackfd (&a, rh); } @@ -1213,53 +1297,53 @@ 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 */ +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[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 */ +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 */ +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[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 */ +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[0], &a); /* F format */ unpackf (opnd[1], &b); -vax_fdiv (&a, &b, 26, FD_BIAS); /* do divide */ -return rpackfd (&b, NULL); /* round and pack */ +vax_fdiv (&a, &b, 26, FD_BIAS); /* do divide */ +return rpackfd (&b, NULL); /* round and pack */ } int32 op_divd (int32 *opnd, int32 *rh) @@ -1268,20 +1352,20 @@ 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 */ +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[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 */ +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 @@ -1297,20 +1381,21 @@ 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 */ +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, LMASK); /* r = r * arg */ - wd = Read (ptr, L_LONG, RD); /* get Cnext */ - ptr = ptr + 4; - unpackf (wd, &c); /* unpack Cnext */ - vax_fadd (&r, &c, LMASK); /* r = r + Cnext */ - res = rpackfd (&r, NULL); } /* round and pack */ +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, LMASK); /* r = r * arg */ + wd = Read (ptr, L_LONG, RD); /* get Cnext */ + ptr = ptr + 4; + unpackf (wd, &c); /* unpack Cnext */ + vax_fadd (&r, &c, LMASK); /* 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); @@ -1324,22 +1409,23 @@ 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 */ +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 */ +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; @@ -1354,22 +1440,23 @@ 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 */ +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 */ +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; diff --git a/VAX/vax_io.c b/VAX/vax_io.c index 8f1f9732..b6e4c258 100644 --- a/VAX/vax_io.c +++ b/VAX/vax_io.c @@ -1,6 +1,6 @@ /* vax_io.c: VAX 3900 Qbus IO simulator - Copyright (c) 1998-2004, Robert M Supnik + Copyright (c) 1998-2005, 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"), @@ -19,91 +19,92 @@ 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 + 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 + qba Qbus adapter - 30-Sep-04 RMS Revised Qbus interface - Moved mem_err, crd_err interrupts here from vax_cpu.c - 09-Sep-04 RMS Integrated powerup into RESET (with -p) - 05-Sep-04 RMS Added CRD interrupt handling - 28-May-04 RMS Revised I/O dispatching (from John Dundas) - 21-Mar-04 RMS Added RXV21 support - 21-Dec-03 RMS Fixed bug in autoconfigure vector assignment; added controls - 21-Nov-03 RMS Added check for interrupt slot conflict (found by Dave Hittner) - 29-Oct-03 RMS Fixed WriteX declaration (found by Mark Pizzolato) - 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 + 25-Jul-05 RMS Revised autoconfiguration algorithm and interface + 30-Sep-04 RMS Revised Qbus interface + Moved mem_err, crd_err interrupts here from vax_cpu.c + 09-Sep-04 RMS Integrated powerup into RESET (with -p) + 05-Sep-04 RMS Added CRD interrupt handling + 28-May-04 RMS Revised I/O dispatching (from John Dundas) + 21-Mar-04 RMS Added RXV21 support + 21-Dec-03 RMS Fixed bug in autoconfigure vector assignment; added controls + 21-Nov-03 RMS Added check for interrupt slot conflict (found by Dave Hittner) + 29-Oct-03 RMS Fixed WriteX declaration (found by Mark Pizzolato) + 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) +#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 +#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 */ +#define CQMEAR_MASK 0x00001FFF /* Qbus page */ /* CQBIC slave error address register */ -#define CQSEAR_MASK 0x000FFFFF /* mem page */ +#define CQSEAR_MASK 0x000FFFFF /* mem page */ /* CQBIC map base register */ -#define CQMBR_MASK 0x1FFF8000 /* 32KB aligned */ +#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 ) +#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 */ +#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 */ -int32 autcon_enb = 1; /* autoconfig enable */ +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 */ +int32 autcon_enb = 1; /* autoconfig enable */ extern uint32 *M; extern UNIT cpu_unit; @@ -132,12 +133,12 @@ t_bool map_addr (uint32 qa, uint32 *ma); t_stat set_autocon (UNIT *uptr, int32 val, char *cptr, void *desc); t_stat show_autocon (FILE *st, UNIT *uptr, int32 val, void *desc); t_stat show_iospace (FILE *st, UNIT *uptr, int32 val, void *desc); - + /* Qbus adapter data structures - qba_dev QBA device descriptor - qba_unit QBA units - qba_reg QBA register list + 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 }; @@ -145,34 +146,37 @@ 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 }, - { FLDATA (AUTOCON, autcon_enb, 0), REG_HRO }, - { NULL } }; + { 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 }, + { FLDATA (AUTOCON, autcon_enb, 0), REG_HRO }, + { NULL } + }; MTAB qba_mod[] = { - { MTAB_XTD|MTAB_VDV|MTAB_NMO, 0, "IOSPACE", NULL, - NULL, &show_iospace }, - { MTAB_XTD|MTAB_VDV, 1, "AUTOCONFIG", "AUTOCONFIG", - &set_autocon, &show_autocon }, - { MTAB_XTD|MTAB_VDV, 0, NULL, "NOAUTOCONFIG", - &set_autocon, NULL }, - { 0 } }; + { MTAB_XTD|MTAB_VDV|MTAB_NMO, 0, "IOSPACE", NULL, + NULL, &show_iospace }, + { MTAB_XTD|MTAB_VDV, 1, "AUTOCONFIG", "AUTOCONFIG", + &set_autocon, &show_autocon }, + { MTAB_XTD|MTAB_VDV, 0, NULL, "NOAUTOCONFIG", + &set_autocon, NULL }, + { 0 } + }; DEVICE qba_dev = { - "QBA", &qba_unit, qba_reg, qba_mod, - 1, 0, 0, 0, 0, 0, - NULL, NULL, &qba_reset, - NULL, NULL, NULL, - &qba_dib, DEV_QBUS }; + "QBA", &qba_unit, qba_reg, qba_mod, + 1, 0, 0, 0, 0, 0, + NULL, NULL, &qba_reset, + NULL, NULL, NULL, + &qba_dib, DEV_QBUS + }; /* IO page dispatches */ @@ -182,16 +186,16 @@ static DIB *iodibp[IOPAGESIZE >> 1]; /* Interrupt request to interrupt action map */ -int32 (*int_ack[IPL_HLVL][32])(); /* int ack routines */ +int32 (*int_ack[IPL_HLVL][32])(); /* int ack routines */ /* Interrupt request to vector map */ -int32 int_vec[IPL_HLVL][32]; /* int req to vector */ - +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 + - read: set DSER<7>, latch addr in MEAR, machine check + - write: set DSER<7>, latch addr in MEAR, MEMERR interrupt */ int32 ReadQb (uint32 pa) @@ -200,8 +204,9 @@ int32 idx, val; idx = (pa & IOPAGEMASK) >> 1; if (iodispR[idx]) { - iodispR[idx] (&val, pa, READ); - return val; } + iodispR[idx] (&val, pa, READ); + return val; + } cq_merr (pa); MACH_CHECK (MCHK_READ); return 0; @@ -213,8 +218,9 @@ int32 idx; idx = (pa & IOPAGEMASK) >> 1; if (iodispW[idx]) { - iodispW[idx] (val, pa, mode); - return; } + iodispW[idx] (val, pa, mode); + return; + } cq_merr (pa); mem_err = 1; return; @@ -223,19 +229,19 @@ return; /* ReadIO - read I/O space Inputs: - pa = physical address - lnt = length (BWLQ) + pa = physical address + lnt = length (BWLQ) Output: - longword of data + 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 */ +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; } @@ -243,23 +249,25 @@ return iod; /* WriteIO - write I/O space Inputs: - pa = physical address - val = data to write, right justified in 32b longword - lnt = length (BWLQ) + pa = physical address + val = data to write, right justified in 32b longword + lnt = length (BWLQ) Outputs: - none + 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); } +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) @@ -268,21 +276,24 @@ 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 */ + 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 */ -if ((ipl < IPL_CRDERR) && crd_err) return IPL_CRDERR; /* crd 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 */ +if (hlt_pin) return IPL_HLTPIN; /* hlt pin int */ +if ((ipl < IPL_MEMERR) && mem_err) return IPL_MEMERR; /* mem err int */ +if ((ipl < IPL_CRDERR) && crd_err) return IPL_CRDERR; /* crd 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; } @@ -293,30 +304,35 @@ int32 get_vector (int32 lvl) int32 i; int32 l = lvl - IPL_HMIN; -if (lvl == IPL_MEMERR) { /* mem error? */ - mem_err = 0; - return SCB_MEMERR; } -if (lvl == IPL_CRDERR) { /* CRD error? */ - crd_err = 0; - return SCB_CRDERR; } -if (lvl > IPL_HMAX) { /* error req lvl? */ - ABORT (STOP_UIPL); } /* unknown intr */ +if (lvl == IPL_MEMERR) { /* mem error? */ + mem_err = 0; + return SCB_MEMERR; + } +if (lvl == IPL_CRDERR) { /* CRD error? */ + crd_err = 0; + return SCB_CRDERR; + } +if (lvl > IPL_HMAX) { /* error req lvl? */ + ABORT (STOP_UIPL); /* unknown intr */ + } 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]; } } + 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 + 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) @@ -324,16 +340,23 @@ 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; } + + 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; } @@ -342,28 +365,33 @@ 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; } + 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; } + + 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; } @@ -372,7 +400,7 @@ return; int32 cqipc_rd (int32 pa) { -return cq_ipc & CQIPC_MASK; /* IPC */ +return cq_ipc & CQIPC_MASK; /* IPC */ } void cqipc_wr (int32 pa, int32 val, int32 lnt) @@ -380,12 +408,13 @@ void cqipc_wr (int32 pa, int32 val, int32 lnt) int32 nval = val; if (lnt < L_LONG) { - int32 sc = (pa & 3) << 3; - nval = val << sc; } + 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; +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; } @@ -402,7 +431,7 @@ 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 @@ -411,27 +440,31 @@ return SCPE_OK; int32 cqmap_rd (int32 pa) { -int32 ma = (pa & CQMAPAMASK) + cq_mbr; /* mem addr */ +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 */ +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 */ +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; } + 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; } @@ -442,47 +475,51 @@ return; int32 cqmem_rd (int32 pa) { -int32 qa = pa & CQMAMASK; /* Qbus addr */ +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 */ +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 */ +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; } +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 */ +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 */ +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; } @@ -491,8 +528,8 @@ return 0; 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 */ +cq_dser = cq_dser | CQDSER_MNX; /* master nxm */ +cq_mear = (pa >> VA_V_VPN) & CQMEAR_MASK; /* page addr */ return; } @@ -501,7 +538,7 @@ return; 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_dser = cq_dser | CQDSER_SNX; /* slave nxm */ cq_sear = (pa >> VA_V_VPN) & CQSEAR_MASK; return; } @@ -510,7 +547,7 @@ return; void ioreset_wr (int32 data) { -reset_all (5); /* from qba on... */ +reset_all (5); /* from qba on... */ return; } @@ -535,13 +572,13 @@ cq_dser = cq_mear = cq_sear = cq_ipc = 0; for (i = 0; i < IPL_HLVL; i++) int_req[i] = 0; return SCPE_OK; } - + /* Qbus 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 + 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) @@ -549,25 +586,30 @@ 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; } - } +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; } @@ -578,23 +620,28 @@ 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; } - } +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; } @@ -603,25 +650,30 @@ 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; } - } +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; } @@ -632,33 +684,38 @@ 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; } - } +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; } - + /* Enable/disable autoconfiguration */ t_stat set_autocon (UNIT *uptr, int32 val, char *cptr, void *desc) { if (cptr != NULL) return SCPE_ARG; autcon_enb = val; -return auto_config (0, 0); +return auto_config (NULL, 0); } /* Show autoconfiguration status */ @@ -685,13 +742,13 @@ 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 */ +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 */ -autcon_enb = 0; /* autoconfig off */ +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 */ +autcon_enb = 0; /* autoconfig off */ return SCPE_OK; } @@ -709,7 +766,7 @@ 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); + fprintf (st, "-%08X", dibp->ba + dibp->lnt - 1); if (dptr->flags & DEV_FLTA) fprintf (st, "*"); return SCPE_OK; } @@ -724,8 +781,8 @@ 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 */ +dptr->flags = dptr->flags | DEV_FLTA; /* floating */ +return auto_config (NULL, 0); /* autoconfigure */ } /* Change device vector */ @@ -748,8 +805,8 @@ 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; -dptr->flags = dptr->flags & ~DEV_FLTA; /* not floating */ -autcon_enb = 0; /* autoconfig off */ +dptr->flags = dptr->flags & ~DEV_FLTA; /* not floating */ +autcon_enb = 0; /* autoconfig off */ return SCPE_OK; } @@ -770,35 +827,37 @@ 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))); } +else { + fprintf (st, "vector=%X", vec); + if (numvec > 1) fprintf (st, "-%X", vec + (4 * (numvec - 1))); + } return SCPE_OK; } - + /* Build dispatch tables */ t_stat build_dsp_tab (DEVICE *dptr, DIB *dibp) { uint32 i, idx; -if ((dptr == NULL) || (dibp == NULL)) return SCPE_IERR; /* validate args */ -for (i = 0; i < dibp->lnt; i = i + 2) { /* create entries */ - idx = ((dibp->ba + i) & IOPAGEMASK) >> 1; /* index into disp */ - if ((iodispR[idx] && dibp->rd && /* conflict? */ - (iodispR[idx] != dibp->rd)) || - (iodispW[idx] && dibp->wr && - (iodispW[idx] != dibp->wr))) { - 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 SCPE_STOP; - } - if (dibp->rd) iodispR[idx] = dibp->rd; /* set rd dispatch */ - if (dibp->wr) iodispW[idx] = dibp->wr; /* set wr dispatch */ - iodibp[idx] = dibp; /* remember DIB */ - } +if ((dptr == NULL) || (dibp == NULL)) return SCPE_IERR; /* validate args */ +for (i = 0; i < dibp->lnt; i = i + 2) { /* create entries */ + idx = ((dibp->ba + i) & IOPAGEMASK) >> 1; /* index into disp */ + if ((iodispR[idx] && dibp->rd && /* conflict? */ + (iodispR[idx] != dibp->rd)) || + (iodispW[idx] && dibp->wr && + (iodispW[idx] != dibp->wr))) { + 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 SCPE_STOP; + } + if (dibp->rd) iodispR[idx] = dibp->rd; /* set rd dispatch */ + if (dibp->wr) iodispW[idx] = dibp->wr; /* set wr dispatch */ + iodibp[idx] = dibp; /* remember DIB */ + } return SCPE_OK; } @@ -809,27 +868,27 @@ t_stat build_int_vec (DEVICE *dptr, DIB *dibp) { int32 i, idx, vec, ilvl, ibit; -if ((dptr == NULL) || (dibp == NULL)) return SCPE_IERR; /* validate args */ +if ((dptr == NULL) || (dibp == NULL)) return SCPE_IERR; /* validate args */ if (dibp->vnum > VEC_DEVMAX) return SCPE_IERR; -for (i = 0; i < dibp->vnum; i++) { /* loop thru vec */ - idx = dibp->vloc + i; /* vector index */ - vec = dibp->vec? (dibp->vec + (i * 4)): 0; /* vector addr */ - ilvl = idx / 32; - ibit = idx % 32; - if ((int_ack[ilvl][ibit] && dibp->ack[i] && /* conflict? */ - (int_ack[ilvl][ibit] != dibp->ack[i])) || - (int_vec[ilvl][ibit] && vec && - (int_vec[ilvl][ibit] != vec))) { - printf ("Device %s interrupt slot conflict at %d\n", - sim_dname (dptr), idx); - if (sim_log) fprintf (sim_log, - "Device %s interrupt slot conflict at %d\n", - sim_dname (dptr), idx); - return SCPE_STOP; - } - if (dibp->ack[i]) int_ack[ilvl][ibit] = dibp->ack[i]; - else if (vec) int_vec[ilvl][ibit] = vec; - } +for (i = 0; i < dibp->vnum; i++) { /* loop thru vec */ + idx = dibp->vloc + i; /* vector index */ + vec = dibp->vec? (dibp->vec + (i * 4)): 0; /* vector addr */ + ilvl = idx / 32; + ibit = idx % 32; + if ((int_ack[ilvl][ibit] && dibp->ack[i] && /* conflict? */ + (int_ack[ilvl][ibit] != dibp->ack[i])) || + (int_vec[ilvl][ibit] && vec && + (int_vec[ilvl][ibit] != vec))) { + printf ("Device %s interrupt slot conflict at %d\n", + sim_dname (dptr), idx); + if (sim_log) fprintf (sim_log, + "Device %s interrupt slot conflict at %d\n", + sim_dname (dptr), idx); + return SCPE_STOP; + } + if (dibp->ack[i]) int_ack[ilvl][ibit] = dibp->ack[i]; + else if (vec) int_vec[ilvl][ibit] = vec; + } return SCPE_OK; } @@ -842,23 +901,26 @@ DEVICE *dptr; DIB *dibp; t_stat r; -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 = 0; i < (IOPAGESIZE >> 1); i++) { /* clear dispatch tab */ - iodispR[i] = NULL; - iodispW[i] = NULL; - iodibp[i] = NULL; } -for (i = 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 (r = build_int_vec (dptr, dibp)) /* add to intr tab */ - return r; - if (r = build_dsp_tab (dptr, dibp)) /* add to dispatch tab */ - return r; - } /* end if enabled */ - } /* end for */ +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 = 0; i < (IOPAGESIZE >> 1); i++) { /* clear dispatch tab */ + iodispR[i] = NULL; + iodispW[i] = NULL; + iodibp[i] = NULL; + } +for (i = 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 (r = build_int_vec (dptr, dibp)) /* add to intr tab */ + return r; + if (r = build_dsp_tab (dptr, dibp)) /* add to dispatch tab */ + return r; + } /* end if enabled */ + } /* end for */ return SCPE_OK; } @@ -870,117 +932,162 @@ uint32 i, j; DEVICE *dptr; DIB *dibp; -if (build_dib_tab ()) return SCPE_OK; /* build IO page */ -for (i = 0, dibp = NULL; i < (IOPAGESIZE >> 1); i++) { /* loop thru entries */ - if (iodibp[i] && (iodibp[i] != dibp)) { /* new block? */ - dibp = iodibp[i]; /* DIB for block */ - for (j = 0, dptr = NULL; sim_devices[j] != NULL; j++) { - if (((DIB*) sim_devices[j]->ctxt) == dibp) { - dptr = sim_devices[j]; /* locate device */ - break; - } /* end if */ - } /* end for j */ - fprintf (st, "%08X - %08X%c\t%s\n", dibp->ba, - dibp->ba + dibp->lnt - 1, - (dptr && (dptr->flags & DEV_FLTA))? '*': ' ', - dptr? sim_dname (dptr): "CPU"); - } /* end if */ - } /* end for i */ +if (build_dib_tab ()) return SCPE_OK; /* build IO page */ +for (i = 0, dibp = NULL; i < (IOPAGESIZE >> 1); i++) { /* loop thru entries */ + if (iodibp[i] && (iodibp[i] != dibp)) { /* new block? */ + dibp = iodibp[i]; /* DIB for block */ + for (j = 0, dptr = NULL; sim_devices[j] != NULL; j++) { + if (((DIB*) sim_devices[j]->ctxt) == dibp) { + dptr = sim_devices[j]; /* locate device */ + break; + } /* end if */ + } /* end for j */ + fprintf (st, "%08X - %08X%c\t%s\n", dibp->ba, + dibp->ba + dibp->lnt - 1, + (dptr && (dptr->flags & DEV_FLTA))? '*': ' ', + dptr? sim_dname (dptr): "CPU"); + } /* end if */ + } /* end for i */ return SCPE_OK; } - -/* Autoconfiguration */ -#define AUTO_DYN 0001 -#define AUTO_VEC 0002 -#define AUTO_MAXC 4 -#define AUTO_CSRBASE 0010 -#define AUTO_VECBASE 0300 +/* Autoconfiguration -struct auto_con { - uint32 amod; - uint32 vmod; - uint32 flags; - uint32 num; - uint32 fix; - char *dnam[AUTO_MAXC]; }; + The table reflects the MicroVAX 3900 microcode, with one addition - the + number of controllers field handles devices where multiple instances + are simulated through a single DEVICE structure (e.g., DZ, VH). -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" } }, + A minus number of vectors indicates a field that should be calculated + but not placed in the DIB (RQ, TQ dynamic vectors) */ - { 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 */ +#define AUTO_MAXC 4 +#define AUTO_CSRBASE 0010 +#define AUTO_VECBASE 0300 - { 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 */ +typedef struct { + char *dnam[AUTO_MAXC]; + int32 numc; + int32 numv; + uint32 amod; + uint32 vmod; + uint32 fixa[AUTO_MAXC]; + uint32 fixv[AUTO_MAXC]; + } AUTO_CON; - { 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 */ - { 0x1f, 0x7, AUTO_VEC, VH_MUXES, 0, { "VH" } }, /* DHU11/DHQ11 */ - - { 0x1f, 0x7 }, /* DMZ32 */ - { 0x1f, 0x7 }, /* CP132 */ - { 0 }, /* padding */ +AUTO_CON auto_tab[] = { + { { NULL }, 1, 2, 0, 8, { 0 } }, /* DLV11J - fx CSRs */ + { { NULL }, 1, 2, 8, 8 }, /* DJ11 */ + { { NULL }, 1, 2, 16, 8 }, /* DH11 */ + { { NULL }, 1, 2, 8, 8 }, /* DQ11 */ + { { NULL }, 1, 2, 8, 8 }, /* DU11 */ + { { NULL }, 1, 2, 8, 8 }, /* DUP11 */ + { { NULL }, 10, 2, 8, 8 }, /* LK11A */ + { { NULL }, 1, 2, 8, 8 }, /* DMC11 */ + { { "DZ" }, DZ_MUXES, 2, 8, 8 }, /* DZ11 */ + { { NULL }, 1, 2, 8, 8 }, /* KMC11 */ + { { NULL }, 1, 2, 8, 8 }, /* LPP11 */ + { { NULL }, 1, 2, 8, 8 }, /* VMV21 */ + { { NULL }, 1, 2, 16, 8 }, /* VMV31 */ + { { NULL }, 1, 2, 8, 8 }, /* DWR70 */ + { { "RL", "RLB" }, 1, 1, 8, 4, {IOBA_RL}, {VEC_RL} }, /* RL11 */ + { { "TS", "TSB", "TSC", "TSD" }, 1, 1, 0, 4, /* TS11 */ + {IOBA_TS, IOBA_TS + 4, IOBA_TS + 8, IOBA_TS + 12}, + {VEC_TS} }, + { { NULL }, 1, 2, 16, 8 }, /* LPA11K */ + { { NULL }, 1, 2, 8, 8 }, /* KW11C */ + { { NULL }, 1, 1, 8, 8 }, /* reserved */ + { { "RX", "RY" }, 1, 1, 8, 4, {IOBA_RX} , {VEC_RX} }, /* RX11/RX211 */ + { { NULL }, 1, 1, 8, 4 }, /* DR11W */ + { { NULL }, 1, 1, 8, 4, { 0, 0 }, { 0 } }, /* DR11B - fx CSRs,vec */ + { { NULL }, 1, 2, 8, 8 }, /* DMP11 */ + { { NULL }, 1, 2, 8, 8 }, /* DPV11 */ + { { NULL }, 1, 2, 8, 8 }, /* ISB11 */ + { { NULL }, 1, 2, 16, 8 }, /* DMV11 */ +/* { { "XU", "XUB" }, 1, 1, 8, 4, {IOBA_XU}, {VEC_XU} }, /* DEUNA */ + { { "XQ", "XQB" }, 1, 1, 0, 4, /* DEQNA */ + {IOBA_XQ,IOBA_XQB}, {VEC_XQ} }, + { { "RQ", "RQB", "RQC", "RQD" }, 1, -1, 4, 4, /* RQDX3 */ + {IOBA_RQ}, {VEC_RQ} }, + { { NULL }, 1, 8, 32, 4 }, /* DMF32 */ + { { NULL }, 1, 2, 16, 8 }, /* KMS11 */ + { { NULL }, 1, 1, 16, 4 }, /* VS100 */ + { { "TQ", "TQB" }, 1, -1, 4, 4, {IOBA_TQ}, {VEC_TQ} }, /* TQK50 */ + { { NULL }, 1, 2, 16, 8 }, /* KMV11 */ + { { "VH" }, VH_MUXES, 2, 16, 8 }, /* DHU11/DHQ11 */ + { { NULL }, 1, 6, 32, 4 }, /* DMZ32 */ + { { NULL }, 1, 6, 32, 4 }, /* CP132 */ + { { NULL }, 1, 2, 64, 8, { 0 } }, /* QVSS - fx CSR */ + { { NULL }, 1, 1, 8, 4 }, /* VS31 */ + { { NULL }, 1, 1, 0, 4, { 0 } }, /* LNV11 - fx CSR */ + { { NULL }, 1, 1, 16, 4 }, /* LNV21/QPSS */ + { { NULL }, 1, 1, 8, 4, { 0 } }, /* QTA - fx CSR */ + { { NULL }, 1, 1, 8, 4 }, /* DSV11 */ + { { NULL }, 1, 2, 8, 8 }, /* CSAM */ + { { NULL }, 1, 2, 8, 8 }, /* ADV11C */ + { { NULL }, 1, 0, 8, 0 }, /* AAV11C */ + { { NULL }, 1, 2, 8, 8, { 0 }, { 0 } }, /* AXV11C - fx CSR,vec */ + { { NULL }, 1, 2, 4, 8, { 0 } }, /* KWV11C - fx CSR */ + { { NULL }, 1, 2, 8, 8, { 0 } }, /* ADV11D - fx CSR */ + { { NULL }, 1, 2, 8, 8, { 0 } }, /* AAV11D - fx CSR */ + { { "QDSS" }, 1, 3, 0, 16, {IOBA_QDSS} }, /* QDSS - fx CSR */ + { { NULL }, -1 } /* end table */ }; -t_stat auto_config (uint32 rank, uint32 nctrl) +t_stat auto_config (char *name, int32 nctrl) { uint32 csr = IOPAGEBASE + AUTO_CSRBASE; uint32 vec = VEC_Q + AUTO_VECBASE; -struct auto_con *autp; +AUTO_CON *autp; DEVICE *dptr; DIB *dibp; -int32 i, j, k; -extern DEVICE *find_dev (char *ptr); +uint32 j, k, vmask, amask; -if (autcon_enb == 0) return SCPE_OK; /* enabled? */ -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 */ +if (autcon_enb == 0) return SCPE_OK; /* enabled? */ +if (name) { /* updating? */ + if (nctrl < 0) return SCPE_ARG; + for (autp = auto_tab; autp->numc >= 0; autp++) { + for (j = 0; (j < AUTO_MAXC) && autp->dnam[j]; j++) { + if (strcmp (name, autp->dnam[j]) == 0) + autp->numc = nctrl; + } + } + } +for (autp = auto_tab; autp->numc >= 0; autp++) { /* loop thru table */ + if (autp->amod) { /* floating csr? */ + amask = autp->amod - 1; + csr = (csr + amask) & ~amask; /* align csr */ + } + 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 (dibp == NULL) return SCPE_IERR; /* not there??? */ + if (autp->amod) { /* dyn csr needed? */ + if (autp->fixa[k]) /* fixed csr avail? */ + dibp->ba = autp->fixa[k]; /* use it */ + else { /* no fixed left */ + dibp->ba = csr; /* set CSR */ + csr += (autp->numc * autp->amod); /* next CSR */ + } /* end else */ + } /* end if dyn csr */ + if (autp->numv && autp->vmod) { /* dyn vec needed? */ + uint32 numv = abs (autp->numv); /* get num vec */ + if (autp->fixv[k]) { /* fixed vec avail? */ + if (autp->numv > 0) + dibp->vec = autp->fixv[k]; /* use it */ + } + else { /* no fixed left */ + vmask = autp->vmod - 1; + vec = (vec + vmask) & ~vmask; /* align vector */ + if (autp->numv > 0) + dibp->vec = vec; /* set vector */ + vec += (autp->numc * numv * 4); + } /* end else */ + } /* end if dyn vec */ + k++; /* next instance */ + } /* end for j */ + if (autp->amod) csr = csr + 2; /* flt CSR? gap */ + } /* end for i */ return SCPE_OK; } diff --git a/VAX/vax_mmu.c b/VAX/vax_mmu.c index 5a2736c5..6b11e458 100644 --- a/VAX/vax_mmu.c +++ b/VAX/vax_mmu.c @@ -1,6 +1,6 @@ -/* vax_mm.c - VAX memory management +/* vax_mmu.c - VAX memory management - Copyright (c) 1998-2004, Robert M Supnik + Copyright (c) 1998-2005, 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"), @@ -19,39 +19,37 @@ 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 + 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-Sep-04 RMS Comment and formating changes - 19-Sep-03 RMS Fixed upper/lower case linkage problems on VMS - 01-Jun-03 RMS Fixed compilation problem with USE_ADDR64 + 30-Sep-04 RMS Comment and formating changes + 19-Sep-03 RMS Fixed upper/lower case linkage problems on VMS + 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 + 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 + 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; +typedef struct { + int32 tag; /* tag */ + int32 pte; /* pte */ + } TLBENT; extern uint32 *M; extern uint32 align[4]; @@ -65,35 +63,36 @@ extern int32 SISR; extern jmp_buf save_env; extern UNIT cpu_unit; -int32 d_p0br, d_p0lr; /* dynamic copies */ -int32 d_p1br, d_p1lr; /* altered per ucode */ +int32 d_p0br, d_p0lr; /* dynamic copies */ +int32 d_p1br, d_p1lr; /* altered per ucode */ int32 d_sbr, d_slr; -extern int32 mchk_va, mchk_ref; /* for mcheck */ +extern int32 mchk_va, mchk_ref; /* for mcheck */ TLBENT stlb[VA_TBSIZE], ptlb[VA_TBSIZE]; static const int32 insert[4] = { - 0x00000000, 0x000000FF, 0x0000FFFF, 0x00FFFFFF }; + 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) -}; + 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); @@ -112,52 +111,55 @@ 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 + 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) } }; + { UDATA (NULL, UNIT_FIX, VA_TBSIZE * 2) }, + { UDATA (NULL, UNIT_FIX, VA_TBSIZE * 2) } + }; REG tlb_reg[] = { - { NULL } }; + { 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 }; - + "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. + 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) + va = virtual address + lnt = length code (BWLQ) + acc = access code (KESU) Output: - returned data, right justified in 32b longword + returned data, right justified in 32b longword */ int32 Read (uint32 va, int32 lnt, int32 acc) @@ -167,50 +169,56 @@ 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 */ +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 */ +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))) & LMASK); } +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))) & LMASK); + } 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)); } +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) + va = virtual address + val = data to be written, right justified in 32b lw + lnt = length code (BWLQ) + acc = access code (KESU) Output: - none + none */ void Write (uint32 va, int32 val, int32 lnt, int32 acc) @@ -221,49 +229,56 @@ 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; } + 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 ((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); } + 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) & LMASK); - wh = (wh & ~insert[bo]) | ((val >> (32 - sc)) & insert[bo]); - WriteL (pa, wl); - WriteL (pa1, wh); } + sc = bo << 3; + wh = ReadL (pa1); + wl = (wl & insert[bo]) | ((val << sc) & LMASK); + 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 & 0xFF) << 24); - wh = (wh & 0xFFFFFF00) | ((val >> 8) & 0xFF); - WriteL (pa, wl); - WriteL (pa1, wh); } + wl = (wl & 0xFF0000FF) | (val << 8); + WriteL (pa, wl); + } +else { + wh = ReadL (pa1); + wl = (wl & 0x00FFFFFF) | ((val & 0xFF) << 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) @@ -271,26 +286,27 @@ 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 */ +*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 + pa = physical address, naturally aligned Output: - returned data, right justified in 32b longword + returned data, right justified in 32b longword */ int32 ReadB (uint32 pa) @@ -298,9 +314,11 @@ 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); } +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); } @@ -309,9 +327,11 @@ 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); } +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); } @@ -335,56 +355,66 @@ 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 + pa = physical address, naturally aligned + val = data to be written, right justified in 32b longword Output: - none + 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); } + 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); } + 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); } +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); } +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 @@ -397,10 +427,10 @@ return; */ #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); } + 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) { @@ -408,58 +438,65 @@ 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 >= d_slr) MM_ERR (PR_LNV); /* system */ - ptead = d_sbr + ptidx; } -else { if (va & VA_P1) { /* P1? */ - if (ptidx < d_p1lr) MM_ERR (PR_LNV); - ptead = d_p1br + ptidx; } - else { /* P0 */ - if (ptidx >= d_p0lr) - MM_ERR (PR_LNV); - ptead = d_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 >= d_slr) MM_ERR (PR_PLNV); - pte = ReadLP (d_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 */ +if (va & VA_S0) { /* system space? */ + if (ptidx >= d_slr) MM_ERR (PR_LNV); /* system */ + ptead = d_sbr + ptidx; + } +else { + if (va & VA_P1) { /* P1? */ + if (ptidx < d_p1lr) MM_ERR (PR_LNV); + ptead = d_p1br + ptidx; + } + else { /* P0 */ + if (ptidx >= d_p0lr) MM_ERR (PR_LNV); + ptead = d_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 >= d_slr) MM_ERR (PR_PLNV); + pte = ReadLP (d_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 */ +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) { d_p0br = P0BR & ~03; -d_p1br = (P1BR - 0x800000) & ~03; /* VA<30> >> 7 */ -d_sbr = (SBR - 0x1000000) & ~03; /* VA<31> >> 7 */ +d_p1br = (P1BR - 0x800000) & ~03; /* VA<30> >> 7 */ +d_sbr = (SBR - 0x1000000) & ~03; /* VA<31> >> 7 */ d_p0lr = (P0LR << 2); -d_p1lr = (P1LR << 2) + 0x800000; /* VA<30> >> 7 */ -d_slr = (SLR << 2) + 0x1000000; /* VA<31> >> 7 */ +d_p1lr = (P1LR << 2) + 0x800000; /* VA<30> >> 7 */ +d_slr = (SLR << 2) + 0x1000000; /* VA<31> >> 7 */ return; } @@ -470,8 +507,9 @@ 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; } + ptlb[i].tag = ptlb[i].pte = -1; + if (stb) stlb[i].tag = stlb[i].pte = -1; + } return; } @@ -498,7 +536,7 @@ 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) @@ -521,10 +559,13 @@ 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; } + 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; } @@ -535,6 +576,6 @@ 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; + stlb[i].tag = ptlb[i].tag = stlb[i].pte = ptlb[i].pte = -1; return SCPE_OK; } diff --git a/VAX/vax_octa.c b/VAX/vax_octa.c index 6d844b2a..e78b86d2 100644 --- a/VAX/vax_octa.c +++ b/VAX/vax_octa.c @@ -1,6 +1,6 @@ /* vax_octa.c - VAX octaword and h_floating instructions - Copyright (c) 2004, Robert M Supnik + Copyright (c) 2004-2005, 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"), @@ -19,13 +19,13 @@ 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 + 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 VAX h_floating instruction set. - 15-Jul-04 RMS Cloned from 32b VAX floating point implementation + 15-Jul-04 RMS Cloned from 32b VAX floating point implementation */ #include "vax_defs.h" @@ -42,31 +42,27 @@ extern int32 Read (uint32 va, int32 size, int32 acc); extern void Write (uint32 va, int32 val, int32 lnt, int32 acc); extern int32 Test (uint32 va, int32 acc, int32 *status); -#define WORDSWAP(x) ((((x) & WMASK) << 16) | (((x) >> 16) & WMASK)) +#define WORDSWAP(x) ((((x) & WMASK) << 16) | (((x) >> 16) & WMASK)) -struct uqp { - uint32 f0; /* low */ - uint32 f1; - uint32 f2; - uint32 f3; /* high */ - }; +typedef struct { + uint32 f0; /* low */ + uint32 f1; + uint32 f2; + uint32 f3; /* high */ + } UQP; -typedef struct uqp UQP; +typedef struct { + int32 sign; + int32 exp; + UQP frac; + } UFPH; -struct ufph { - int32 sign; - int32 exp; - struct uqp frac; - }; - -typedef struct ufph UFPH; - -#define UH_NM_H 0x80000000 /* normalized */ -#define UH_FRND 0x00000080 /* F round */ -#define UH_DRND 0x00000080 /* D round */ -#define UH_GRND 0x00000400 /* G round */ -#define UH_HRND 0x00004000 /* H round */ -#define UH_V_NM 127 +#define UH_NM_H 0x80000000 /* normalized */ +#define UH_FRND 0x00000080 /* F round */ +#define UH_DRND 0x00000080 /* D round */ +#define UH_GRND 0x00000400 /* G round */ +#define UH_HRND 0x00004000 /* H round */ +#define UH_V_NM 127 int32 op_tsth (int32 val); int32 op_cmph (int32 *hf1, int32 *hf2); @@ -106,7 +102,7 @@ int32 h_rpackg (UFPH *a, int32 *rl); int32 h_rpackh (UFPH *a, int32 *hflt); static int32 z_octa[4] = { 0, 0, 0, 0 }; - + /* Octaword instructions */ int32 op_octa (int32 *opnd, int32 cc, int32 opc, int32 acc, int32 spec, int32 va) @@ -118,305 +114,307 @@ switch (opc) { /* PUSHAO - opnd[0] = src.ao + opnd[0] = src.ao */ -case PUSHAO: - Write (SP - 4, opnd[0], L_LONG, WA); /* push operand */ - SP = SP - 4; /* decr stack ptr */ - CC_IIZP_L (opnd[0]); /* set cc's */ - break; + case PUSHAO: + Write (SP - 4, opnd[0], L_LONG, WA); /* push operand */ + SP = SP - 4; /* decr stack ptr */ + CC_IIZP_L (opnd[0]); /* set cc's */ + break; /* MOVAO - opnd[0] = src.ro - opnd[1:2] = dst.wl - spec = last specifier - va = address if last specifier is memory + opnd[0] = src.ro + opnd[1:2] = dst.wl + spec = last specifier + va = address if last specifier is memory */ -case MOVAO: - h_write_l (spec, va, opnd[0], acc); /* write operand */ - CC_IIZP_L (opnd[0]); /* set cc's */ - break; + case MOVAO: + h_write_l (spec, va, opnd[0], acc); /* write operand */ + CC_IIZP_L (opnd[0]); /* set cc's */ + break; /* CLRO - opnd[0:1] = dst.wl - spec = last specifier - va = address if last specifier is memory + opnd[0:1] = dst.wl + spec = last specifier + va = address if last specifier is memory */ -case CLRO: - h_write_o (spec, va, z_octa, acc); /* write 0's */ - CC_ZZ1P; /* set cc's */ - break; + case CLRO: + h_write_o (spec, va, z_octa, acc); /* write 0's */ + CC_ZZ1P; /* set cc's */ + break; /* TSTH - opnd[0:3] = src.rh + opnd[0:3] = src.rh */ -case TSTH: - r = op_tsth (opnd[0]); /* test for 0 */ - CC_IIZZ_FP (r); /* set cc's */ - break; + case TSTH: + r = op_tsth (opnd[0]); /* test for 0 */ + CC_IIZZ_FP (r); /* set cc's */ + break; /* MOVO, MOVH, MNEGH - opnd[0:3] = src.ro - opnd[4:5] = dst.wo - spec = last specifier - va = address if last specifier is memory + opnd[0:3] = src.ro + opnd[4:5] = dst.wo + spec = last specifier + va = address if last specifier is memory */ -case MOVO: - h_write_o (spec, va, opnd, acc); /* write src */ - CC_IIZP_O (opnd[0], opnd[1], opnd[2], opnd[3]); /* set cc's */ - break; + case MOVO: + h_write_o (spec, va, opnd, acc); /* write src */ + CC_IIZP_O (opnd[0], opnd[1], opnd[2], opnd[3]); /* set cc's */ + break; -case MOVH: - if (r = op_tsth (opnd[0])) /* test for 0 */ - h_write_o (spec, va, opnd, acc); /* nz, write result */ - else h_write_o (spec, va, z_octa, acc); /* zero, write 0 */ - CC_IIZP_FP (r); /* set cc's */ - break; + case MOVH: + if (r = op_tsth (opnd[0])) /* test for 0 */ + h_write_o (spec, va, opnd, acc); /* nz, write result */ + else h_write_o (spec, va, z_octa, acc); /* zero, write 0 */ + CC_IIZP_FP (r); /* set cc's */ + break; -case MNEGH: - if (r = op_tsth (opnd[0])) { /* test for 0 */ - opnd[0] = opnd[0] ^ FPSIGN; /* nz, invert sign */ - h_write_o (spec, va, opnd, acc); /* write result */ - } - else h_write_o (spec, va, z_octa, acc); /* zero, write 0 */ - CC_IIZZ_FP (r); /* set cc's */ - break; + case MNEGH: + if (r = op_tsth (opnd[0])) { /* test for 0 */ + opnd[0] = opnd[0] ^ FPSIGN; /* nz, invert sign */ + h_write_o (spec, va, opnd, acc); /* write result */ + } + else h_write_o (spec, va, z_octa, acc); /* zero, write 0 */ + CC_IIZZ_FP (r); /* set cc's */ + break; /* CMPH - opnd[0:3] = src1.rh - opnd[4:7] = src2.rh + opnd[0:3] = src1.rh + opnd[4:7] = src2.rh */ -case CMPH: - cc = op_cmph (opnd + 0, opnd + 4); /* set cc's */ - break; + case CMPH: + cc = op_cmph (opnd + 0, opnd + 4); /* set cc's */ + break; /* CVTBH, CVTWH, CVTLH - opnd[0] = src.rx - opnd[1:2] = dst.wh - spec = last specifier - va = address if last specifier is memory + opnd[0] = src.rx + opnd[1:2] = dst.wh + spec = last specifier + va = address if last specifier is memory */ -case CVTBH: - r = op_cvtih (SXTB (opnd[0]), r_octa); /* convert */ - h_write_o (spec, va, r_octa, acc); /* write reslt */ - CC_IIZZ_FP (r); /* set cc's */ - break; + case CVTBH: + r = op_cvtih (SXTB (opnd[0]), r_octa); /* convert */ + h_write_o (spec, va, r_octa, acc); /* write reslt */ + CC_IIZZ_FP (r); /* set cc's */ + break; -case CVTWH: - r = op_cvtih (SXTW (opnd[0]), r_octa); /* convert */ - h_write_o (spec, va, r_octa, acc); /* write result */ - CC_IIZZ_FP (r); /* set cc's */ - break; + case CVTWH: + r = op_cvtih (SXTW (opnd[0]), r_octa); /* convert */ + h_write_o (spec, va, r_octa, acc); /* write result */ + CC_IIZZ_FP (r); /* set cc's */ + break; -case CVTLH: - r = op_cvtih (opnd[0], r_octa); /* convert */ - h_write_o (spec, va, r_octa, acc); /* write result */ - CC_IIZZ_FP (r); /* set cc's */ - break; + case CVTLH: + r = op_cvtih (opnd[0], r_octa); /* convert */ + h_write_o (spec, va, r_octa, acc); /* write result */ + CC_IIZZ_FP (r); /* set cc's */ + break; /* CVTHB, CVTHW, CVTHL, CVTRHL - opnd[0:3] = src.rh - opnd[4:5] = dst.wx - spec = last specifier - va = address if last specifier is memory + opnd[0:3] = src.rh + opnd[4:5] = dst.wx + spec = last specifier + va = address if last specifier is memory */ -case CVTHB: - r = op_cvthi (opnd, &temp, opc) & BMASK; /* convert */ - h_write_b (spec, va, r, acc); /* write result */ - CC_IIZZ_B (r); /* set cc's */ - cc = cc | temp; /* or in V */ - break; + case CVTHB: + r = op_cvthi (opnd, &temp, opc) & BMASK; /* convert */ + h_write_b (spec, va, r, acc); /* write result */ + CC_IIZZ_B (r); /* set cc's */ + cc = cc | temp; /* or in V */ + break; -case CVTHW: - r = op_cvthi (opnd, &temp, opc) & WMASK; /* convert */ - h_write_w (spec, va, r, acc); /* write result */ - CC_IIZZ_W (r); /* set cc's */ - cc = cc | temp; /* or in V */ - break; + case CVTHW: + r = op_cvthi (opnd, &temp, opc) & WMASK; /* convert */ + h_write_w (spec, va, r, acc); /* write result */ + CC_IIZZ_W (r); /* set cc's */ + cc = cc | temp; /* or in V */ + break; -case CVTHL: case CVTRHL: - r = op_cvthi (opnd, &temp, opc) & LMASK; /* convert */ - h_write_l (spec, va, r, acc); /* write result */ - CC_IIZZ_L (r); /* set cc's */ - cc = cc | temp; /* or in V */ - break; + case CVTHL: case CVTRHL: + r = op_cvthi (opnd, &temp, opc) & LMASK; /* convert */ + h_write_l (spec, va, r, acc); /* write result */ + CC_IIZZ_L (r); /* set cc's */ + cc = cc | temp; /* or in V */ + break; /* CVTFH - opnd[0] = src.rf - opnd[1:2] = dst.wh - spec = last specifier - va = address if last specifier is memory + opnd[0] = src.rf + opnd[1:2] = dst.wh + spec = last specifier + va = address if last specifier is memory */ -case CVTFH: - r = op_cvtfdh (opnd[0], 0, r_octa); /* convert */ - h_write_o (spec, va, r_octa, acc); /* write result */ - CC_IIZZ_FP (r); /* set cc's */ - break; + case CVTFH: + r = op_cvtfdh (opnd[0], 0, r_octa); /* convert */ + h_write_o (spec, va, r_octa, acc); /* write result */ + CC_IIZZ_FP (r); /* set cc's */ + break; /* CVTDH, CVTGH - opnd[0:1] = src.rx - opnd[2:3] = dst.wh - spec = last specifier - va = address if last specifier is memory + opnd[0:1] = src.rx + opnd[2:3] = dst.wh + spec = last specifier + va = address if last specifier is memory */ -case CVTDH: - r = op_cvtfdh (opnd[0], opnd[1], r_octa); /* convert */ - h_write_o (spec, va, r_octa, acc); /* write result */ - CC_IIZZ_FP (r); /* set cc's */ - break; + case CVTDH: + r = op_cvtfdh (opnd[0], opnd[1], r_octa); /* convert */ + h_write_o (spec, va, r_octa, acc); /* write result */ + CC_IIZZ_FP (r); /* set cc's */ + break; -case CVTGH: - r = op_cvtgh (opnd[0], opnd[1], r_octa); /* convert */ - h_write_o (spec, va, r_octa, acc); /* write result */ - CC_IIZZ_FP (r); /* set cc's */ - break; + case CVTGH: + r = op_cvtgh (opnd[0], opnd[1], r_octa); /* convert */ + h_write_o (spec, va, r_octa, acc); /* write result */ + CC_IIZZ_FP (r); /* set cc's */ + break; /* CVTHF, CVTHD, CVTHG - opnd[0:3] = src.rh - opnd[4:5] = dst.wx - spec = last specifier - va = address if last specifier is memory + opnd[0:3] = src.rh + opnd[4:5] = dst.wx + spec = last specifier + va = address if last specifier is memory */ -case CVTHF: - r = op_cvthfd (opnd, NULL); /* convert */ - h_write_l (spec, va, r, acc); /* write result */ - CC_IIZZ_FP (r); /* set cc's */ - break; + case CVTHF: + r = op_cvthfd (opnd, NULL); /* convert */ + h_write_l (spec, va, r, acc); /* write result */ + CC_IIZZ_FP (r); /* set cc's */ + break; -case CVTHD: - r = op_cvthfd (opnd, &rh); /* convert */ - h_write_q (spec, va, r, rh, acc); /* write result */ - CC_IIZZ_FP (r); /* set cc's */ - break; + case CVTHD: + r = op_cvthfd (opnd, &rh); /* convert */ + h_write_q (spec, va, r, rh, acc); /* write result */ + CC_IIZZ_FP (r); /* set cc's */ + break; -case CVTHG: - r = op_cvthg (opnd, &rh); /* convert */ - h_write_q (spec, va, r, rh, acc); /* write result */ - CC_IIZZ_FP (r); /* set cc's */ - break; + case CVTHG: + r = op_cvthg (opnd, &rh); /* convert */ + h_write_q (spec, va, r, rh, acc); /* write result */ + CC_IIZZ_FP (r); /* set cc's */ + break; /* ADDH2, SUBH2, MULH2, DIVH2 - op[0:3] = src.rh - op[4:7] = dst.mh - spec = last specifier - va = address if last specifier is memory + op[0:3] = src.rh + op[4:7] = dst.mh + spec = last specifier + va = address if last specifier is memory ADDH3, SUBH3, MULH3, DIVH3 - op[0:3] = src1.rh - op[4:7] = src2.rh - op[8:9] = dst.wh - spec = last specifier - va = address if last specifier is memory + op[0:3] = src1.rh + op[4:7] = src2.rh + op[8:9] = dst.wh + spec = last specifier + va = address if last specifier is memory */ -case ADDH2: case ADDH3: - r = op_addh (opnd, r_octa, FALSE); /* add */ - h_write_o (spec, va, r_octa, acc); /* write result */ - CC_IIZZ_FP (r); /* set cc's */ - break; + case ADDH2: case ADDH3: + r = op_addh (opnd, r_octa, FALSE); /* add */ + h_write_o (spec, va, r_octa, acc); /* write result */ + CC_IIZZ_FP (r); /* set cc's */ + break; -case SUBH2: case SUBH3: - r = op_addh (opnd, r_octa, TRUE); /* subtract */ - h_write_o (spec, va, r_octa, acc); /* write result */ - CC_IIZZ_FP (r); /* set cc's */ - break; + case SUBH2: case SUBH3: + r = op_addh (opnd, r_octa, TRUE); /* subtract */ + h_write_o (spec, va, r_octa, acc); /* write result */ + CC_IIZZ_FP (r); /* set cc's */ + break; -case MULH2: case MULH3: - r = op_mulh (opnd, r_octa); /* multiply */ - h_write_o (spec, va, r_octa, acc); /* write result */ - CC_IIZZ_FP (r); /* set cc's */ - break; + case MULH2: case MULH3: + r = op_mulh (opnd, r_octa); /* multiply */ + h_write_o (spec, va, r_octa, acc); /* write result */ + CC_IIZZ_FP (r); /* set cc's */ + break; -case DIVH2: case DIVH3: - r = op_divh (opnd, r_octa); /* divide */ - h_write_o (spec, va, r_octa, acc); /* write result */ - CC_IIZZ_FP (r); /* set cc's */ - break; + case DIVH2: case DIVH3: + r = op_divh (opnd, r_octa); /* divide */ + h_write_o (spec, va, r_octa, acc); /* write result */ + CC_IIZZ_FP (r); /* set cc's */ + break; /* ACBH - - opnd[0:3] = limit.rh - opnd[4:7] = add.rh - opnd[8:11] = index.mh - spec = last specifier - va = last va - brdest = branch destination + + opnd[0:3] = limit.rh + opnd[4:7] = add.rh + opnd[8:11] = index.mh + spec = last specifier + va = last va + brdest = branch destination */ -case ACBH: - r = op_addh (opnd + 4, r_octa, FALSE); /* add + index */ - temp = op_cmph (r_octa, opnd); /* result : limit */ - h_write_o (spec, va, r_octa, acc); /* write 2nd */ - if ((temp & CC_Z) || ((opnd[4] & FPSIGN)? /* test br cond */ - !(temp & CC_N): (temp & CC_N))) - cc = cc | LSIGN; /* hack for branch */ - break; + case ACBH: + r = op_addh (opnd + 4, r_octa, FALSE); /* add + index */ + temp = op_cmph (r_octa, opnd); /* result : limit */ + h_write_o (spec, va, r_octa, acc); /* write 2nd */ + if ((temp & CC_Z) || ((opnd[4] & FPSIGN)? /* test br cond */ + !(temp & CC_N): (temp & CC_N))) + cc = cc | LSIGN; /* hack for branch */ + break; /* POLYH - opnd[0:3] = arg.rh - opnd[4] = deg.rb - opnd[5] = table.ah + opnd[0:3] = arg.rh + opnd[4] = deg.rb + opnd[5] = table.ah */ - -case POLYH: - op_polyh (opnd, acc); /* eval polynomial */ - CC_IIZZ_FP (R[0]); /* set cc's */ - break; + + case POLYH: + op_polyh (opnd, acc); /* eval polynomial */ + CC_IIZZ_FP (R[0]); /* set cc's */ + break; /* EMODH - opnd[0:3] = multiplier - opnd[4] = extension - opnd[5:8] = multiplicand - opnd[9:10] = integer destination (int.wl) - opnd[11:12] = floating destination (flt.wh) - spec = last specifier - va = address if last specifier is memory + opnd[0:3] = multiplier + opnd[4] = extension + opnd[5:8] = multiplicand + opnd[9:10] = integer destination (int.wl) + opnd[11:12] = floating destination (flt.wh) + spec = last specifier + va = address if last specifier is memory */ -case EMODH: - r = op_emodh (opnd, r_octa, &temp, &flg); /* extended mod */ - if (opnd[11] < 0) { /* 2nd memory? */ - Read (opnd[12], L_BYTE, WA); /* prove write */ - Read ((opnd[12] + 15) & LMASK, L_BYTE, WA); } - if (opnd[9] >= 0) R[opnd[9]] = temp; /* store 1st */ - else Write (opnd[10], temp, L_LONG, WA); - h_write_o (spec, va, r_octa, acc); /* write 2nd */ - CC_IIZZ_FP (r); /* set cc's */ - if (flg) { V_INTOV; } /* int ovflo? */ - break; + case EMODH: + r = op_emodh (opnd, r_octa, &temp, &flg); /* extended mod */ + if (opnd[11] < 0) { /* 2nd memory? */ + Read (opnd[12], L_BYTE, WA); /* prove write */ + Read ((opnd[12] + 15) & LMASK, L_BYTE, WA); + } + if (opnd[9] >= 0) R[opnd[9]] = temp; /* store 1st */ + else Write (opnd[10], temp, L_LONG, WA); + h_write_o (spec, va, r_octa, acc); /* write 2nd */ + CC_IIZZ_FP (r); /* set cc's */ + if (flg) { V_INTOV; } /* int ovflo? */ + break; + + default: + RSVD_INST_FAULT; + } -default: - RSVD_INST_FAULT; - } return cc; } - + /* Test h_floating Note that only the high 32b is processed. @@ -424,9 +422,9 @@ return cc; int32 op_tsth (int32 val) { -if (val & H_EXP) return val; /* non-zero? */ -if (val & FPSIGN) RSVD_OPND_FAULT; /* reserved? */ -return 0; /* clean 0 */ +if (val & H_EXP) return val; /* non-zero? */ +if (val & FPSIGN) RSVD_OPND_FAULT; /* reserved? */ +return 0; /* clean 0 */ } /* Compare h_floating */ @@ -436,36 +434,36 @@ int32 op_cmph (int32 *hf1, int32 *hf2) UFPH a, b; int32 r; -h_unpackh (hf1, &a); /* unpack op1 */ -h_unpackh (hf2, &b); /* unpack op2 */ -if (a.sign != b.sign) return (a.sign? CC_N: 0); /* opp signs? */ -if (a.exp != b.exp) r = a.exp - b.exp; /* cmp exp */ -else r = qp_cmp (&a.frac, &b.frac); /* if =, cmp frac */ -if (r < 0) return (a.sign? 0: CC_N); /* !=, maybe set N */ +h_unpackh (hf1, &a); /* unpack op1 */ +h_unpackh (hf2, &b); /* unpack op2 */ +if (a.sign != b.sign) return (a.sign? CC_N: 0); /* opp signs? */ +if (a.exp != b.exp) r = a.exp - b.exp; /* cmp exp */ +else r = qp_cmp (&a.frac, &b.frac); /* if =, cmp frac */ +if (r < 0) return (a.sign? 0: CC_N); /* !=, maybe set N */ if (r > 0) return (a.sign? CC_N: 0); -return CC_Z; /* =, set Z */ +return CC_Z; /* =, set Z */ } - + /* Integer to h_floating convert */ int32 op_cvtih (int32 val, int32 *hf) { UFPH a; -if (val == 0) { /* zero? */ - hf[0] = hf[1] = hf[2] = hf[3] = 0; /* result is 0 */ - return 0; - } -if (val < 0) { /* negative? */ - a.sign = FPSIGN; /* sign = - */ - val = -val; - } -else a.sign = 0; /* else sign = + */ -a.exp = 32 + H_BIAS; /* initial exp */ -a.frac.f3 = val & LMASK; /* fraction hi */ +if (val == 0) { /* zero? */ + hf[0] = hf[1] = hf[2] = hf[3] = 0; /* result is 0 */ + return 0; + } +if (val < 0) { /* negative? */ + a.sign = FPSIGN; /* sign = - */ + val = -val; + } +else a.sign = 0; /* else sign = + */ +a.exp = 32 + H_BIAS; /* initial exp */ +a.frac.f3 = val & LMASK; /* fraction hi */ a.frac.f2 = a.frac.f1 = a.frac.f0 = 0; -h_normh (&a); /* normalize */ -return h_rpackh (&a, hf); /* round and pack */ +h_normh (&a); /* normalize */ +return h_rpackh (&a, hf); /* round and pack */ } /* H_floating to integer convert */ @@ -477,22 +475,23 @@ int32 lnt = opc & 03; int32 ubexp; static uint32 maxv[4] = { 0x7F, 0x7FFF, 0x7FFFFFFF, 0x7FFFFFFF }; -*flg = 0; /* clear ovflo */ -h_unpackh (hf, &a); /* unpack */ -ubexp = a.exp - H_BIAS; /* unbiased exp */ -if ((a.exp == 0) || (ubexp < 0)) return 0; /* true zero or frac? */ -if (ubexp <= UH_V_NM) { /* exp in range? */ - qp_rsh (&a.frac, UH_V_NM - ubexp); /* leave rnd bit */ - if (lnt == 03) qp_inc (&a.frac); /* if CVTR, round */ - qp_rsh (&a.frac, 1); /* now justified */ - if (a.frac.f3 || a.frac.f2 || a.frac.f1 || - (a.frac.f0 > (maxv[lnt] + (a.sign? 1: 0)))) *flg = CC_V; - } -else { *flg = CC_V; /* always ovflo */ - if (ubexp > (UH_V_NM + 32)) return 0; /* in ext range? */ - qp_lsh (&a.frac, ubexp - UH_V_NM - 1); /* no rnd bit */ - } -return (a.sign? NEG (a.frac.f0): a.frac.f0); /* return lo frac */ +*flg = 0; /* clear ovflo */ +h_unpackh (hf, &a); /* unpack */ +ubexp = a.exp - H_BIAS; /* unbiased exp */ +if ((a.exp == 0) || (ubexp < 0)) return 0; /* true zero or frac? */ +if (ubexp <= UH_V_NM) { /* exp in range? */ + qp_rsh (&a.frac, UH_V_NM - ubexp); /* leave rnd bit */ + if (lnt == 03) qp_inc (&a.frac); /* if CVTR, round */ + qp_rsh (&a.frac, 1); /* now justified */ + if (a.frac.f3 || a.frac.f2 || a.frac.f1 || + (a.frac.f0 > (maxv[lnt] + (a.sign? 1: 0)))) *flg = CC_V; + } +else { + *flg = CC_V; /* always ovflo */ + if (ubexp > (UH_V_NM + 32)) return 0; /* in ext range? */ + qp_lsh (&a.frac, ubexp - UH_V_NM - 1); /* no rnd bit */ + } +return (a.sign? NEG (a.frac.f0): a.frac.f0); /* return lo frac */ } /* Floating to floating convert - F/D to H, G to H, H to F/D, H to G */ @@ -501,49 +500,49 @@ int32 op_cvtfdh (int32 vl, int32 vh, int32 *hflt) { UFPH a; -h_unpackfd (vl, vh, &a); /* unpack f/d */ -a.exp = a.exp - FD_BIAS + H_BIAS; /* adjust exp */ -return h_rpackh (&a, hflt); /* round and pack */ +h_unpackfd (vl, vh, &a); /* unpack f/d */ +a.exp = a.exp - FD_BIAS + H_BIAS; /* adjust exp */ +return h_rpackh (&a, hflt); /* round and pack */ } int32 op_cvtgh (int32 vl, int32 vh, int32 *hflt) { UFPH a; -h_unpackg (vl, vh, &a); /* unpack g */ -a.exp = a.exp - G_BIAS + H_BIAS; /* adjust exp */ -return h_rpackh (&a, hflt); /* round and pack */ +h_unpackg (vl, vh, &a); /* unpack g */ +a.exp = a.exp - G_BIAS + H_BIAS; /* adjust exp */ +return h_rpackh (&a, hflt); /* round and pack */ } int32 op_cvthfd (int32 *hflt, int32 *rh) { UFPH a; -h_unpackh (hflt, &a); /* unpack h */ -a.exp = a.exp - H_BIAS + FD_BIAS; /* adjust exp */ -return h_rpackfd (&a, rh); /* round and pack */ +h_unpackh (hflt, &a); /* unpack h */ +a.exp = a.exp - H_BIAS + FD_BIAS; /* adjust exp */ +return h_rpackfd (&a, rh); /* round and pack */ } int32 op_cvthg (int32 *hflt, int32 *rh) { UFPH a; -h_unpackh (hflt, &a); /* unpack h */ -a.exp = a.exp - H_BIAS + G_BIAS; /* adjust exp */ -return h_rpackg (&a, rh); /* round and pack */ +h_unpackh (hflt, &a); /* unpack h */ +a.exp = a.exp - H_BIAS + G_BIAS; /* adjust exp */ +return h_rpackg (&a, rh); /* round and pack */ } - + /* Floating add and subtract */ int32 op_addh (int32 *opnd, int32 *hflt, t_bool sub) { UFPH a, b; -h_unpackh (&opnd[0], &a); /* unpack s1, s2 */ +h_unpackh (&opnd[0], &a); /* unpack s1, s2 */ h_unpackh (&opnd[4], &b); -if (sub) a.sign = a.sign ^ FPSIGN; /* sub? -s1 */ -vax_hadd (&a, &b); /* do add */ -return h_rpackh (&a, hflt); /* round and pack */ +if (sub) a.sign = a.sign ^ FPSIGN; /* sub? -s1 */ +vax_hadd (&a, &b); /* do add */ +return h_rpackh (&a, hflt); /* round and pack */ } /* Floating multiply */ @@ -551,11 +550,11 @@ return h_rpackh (&a, hflt); /* round and pack */ int32 op_mulh (int32 *opnd, int32 *hflt) { UFPH a, b; - -h_unpackh (&opnd[0], &a); /* unpack s1, s2 */ + +h_unpackh (&opnd[0], &a); /* unpack s1, s2 */ h_unpackh (&opnd[4], &b); -vax_hmul (&a, &b); /* do multiply */ -return h_rpackh (&a, hflt); /* round and pack */ +vax_hmul (&a, &b); /* do multiply */ +return h_rpackh (&a, hflt); /* round and pack */ } /* Floating divide */ @@ -564,12 +563,12 @@ int32 op_divh (int32 *opnd, int32 *hflt) { UFPH a, b; -h_unpackh (&opnd[0], &a); /* unpack s1, s2 */ +h_unpackh (&opnd[0], &a); /* unpack s1, s2 */ h_unpackh (&opnd[4], &b); -vax_hdiv (&a, &b); /* do divide */ -return h_rpackh (&a, hflt); /* round and pack */ +vax_hdiv (&a, &b); /* do divide */ +return h_rpackh (&a, hflt); /* round and pack */ } - + /* Polynomial evaluation The most mis-implemented instruction in the VAX (probably here too). @@ -585,28 +584,28 @@ int32 deg = opnd[4]; int32 ptr = opnd[5]; int32 i, wd[4], res[4]; -if (deg > 31) RSVD_OPND_FAULT; /* deg > 31? fault */ -h_unpackh (&opnd[0], &a); /* unpack arg */ -wd[0] = Read (ptr, L_LONG, RD); /* get C0 */ +if (deg > 31) RSVD_OPND_FAULT; /* deg > 31? fault */ +h_unpackh (&opnd[0], &a); /* unpack arg */ +wd[0] = Read (ptr, L_LONG, RD); /* get C0 */ wd[1] = Read (ptr + 4, L_LONG, RD); wd[2] = Read (ptr + 8, L_LONG, RD); wd[3] = Read (ptr + 12, L_LONG, RD); -ptr = ptr + 16; /* adv ptr */ -h_unpackh (wd, &r); /* unpack C0 */ -h_rpackh (&r, res); /* first result */ -for (i = 0; (i < deg) && a.exp; i++) { /* loop */ - h_unpackh (res, &r); /* unpack result */ - vax_hmul (&r, &a); /* r = r * arg */ - wd[0] = Read (ptr, L_LONG, RD); /* get Cn */ - wd[1] = Read (ptr + 4, L_LONG, RD); - wd[2] = Read (ptr + 8, L_LONG, RD); - wd[3] = Read (ptr + 12, L_LONG, RD); - ptr = ptr + 16; - h_unpackh (wd, &c); /* unpack Cnext */ - vax_hadd (&r, &c); /* r = r + Cnext */ - h_rpackh (&r, res); /* round and pack */ - } -R[0] = res[0]; /* result */ +ptr = ptr + 16; /* adv ptr */ +h_unpackh (wd, &r); /* unpack C0 */ +h_rpackh (&r, res); /* first result */ +for (i = 0; (i < deg) && a.exp; i++) { /* loop */ + h_unpackh (res, &r); /* unpack result */ + vax_hmul (&r, &a); /* r = r * arg */ + wd[0] = Read (ptr, L_LONG, RD); /* get Cn */ + wd[1] = Read (ptr + 4, L_LONG, RD); + wd[2] = Read (ptr + 8, L_LONG, RD); + wd[3] = Read (ptr + 12, L_LONG, RD); + ptr = ptr + 16; + h_unpackh (wd, &c); /* unpack Cnext */ + vax_hadd (&r, &c); /* r = r + Cnext */ + h_rpackh (&r, res); /* round and pack */ + } +R[0] = res[0]; /* result */ R[1] = res[1]; R[2] = res[2]; R[3] = res[3]; @@ -626,14 +625,14 @@ int32 op_emodh (int32 *opnd, int32 *hflt, int32 *intgr, int32 *flg) { UFPH a, b; -h_unpackh (&opnd[0], &a); /* unpack operands */ +h_unpackh (&opnd[0], &a); /* unpack operands */ h_unpackh (&opnd[5], &b); -a.frac.f0 = a.frac.f0 | opnd[4]; /* extend src1 */ -vax_hmul (&a, &b); /* multiply */ -vax_hmod (&a, intgr, flg); /* sep int & frac */ -return h_rpackh (&a, hflt); /* round and pack frac */ +a.frac.f0 = a.frac.f0 | opnd[4]; /* extend src1 */ +vax_hmul (&a, &b); /* multiply */ +vax_hmod (&a, intgr, flg); /* sep int & frac */ +return h_rpackh (&a, hflt); /* round and pack frac */ } - + /* Unpacked floating point routines */ /* Floating add */ @@ -643,32 +642,33 @@ void vax_hadd (UFPH *a, UFPH *b) int32 ediff; UFPH t; -if (a->exp == 0) { /* s1 = 0? */ - *a = *b; /* result is s2 */ - return; - } -if (b->exp == 0) return; /* s2 = 0? */ -if ((a->exp < b->exp) || /* |s1| < |s2|? */ +if (a->exp == 0) { /* s1 = 0? */ + *a = *b; /* result is s2 */ + return; + } +if (b->exp == 0) return; /* s2 = 0? */ +if ((a->exp < b->exp) || /* |s1| < |s2|? */ ((a->exp == b->exp) && (qp_cmp (&a->frac, &b->frac) < 0))) { - t = *a; /* swap */ - *a = *b; - *b = t; - } -ediff = a->exp - b->exp; /* exp diff */ -if (a->sign ^ b->sign) { /* eff sub? */ - qp_neg (&b->frac); /* negate fraction */ - if (ediff) qp_rsh_s (&b->frac, ediff, 1); /* denormalize */ - qp_add (&a->frac, &b->frac); /* "add" frac */ - h_normh (a); /* normalize */ - } -else { if (ediff) qp_rsh (&b->frac, ediff); /* add, denormalize */ - qp_add (&a->frac, &b->frac); /* add frac */ - if (qp_cmp (&a->frac, &b->frac) < 0) { /* chk for carry */ - qp_rsh (&a->frac, 1); /* renormalize */ - a->frac.f3 = a->frac.f3 | UH_NM_H; /* add norm bit */ - a->exp = a->exp + 1; /* incr exp */ - } - } + t = *a; /* swap */ + *a = *b; + *b = t; + } +ediff = a->exp - b->exp; /* exp diff */ +if (a->sign ^ b->sign) { /* eff sub? */ + qp_neg (&b->frac); /* negate fraction */ + if (ediff) qp_rsh_s (&b->frac, ediff, 1); /* denormalize */ + qp_add (&a->frac, &b->frac); /* "add" frac */ + h_normh (a); /* normalize */ + } +else { + if (ediff) qp_rsh (&b->frac, ediff); /* add, denormalize */ + qp_add (&a->frac, &b->frac); /* add frac */ + if (qp_cmp (&a->frac, &b->frac) < 0) { /* chk for carry */ + qp_rsh (&a->frac, 1); /* renormalize */ + a->frac.f3 = a->frac.f3 | UH_NM_H; /* add norm bit */ + a->exp = a->exp + 1; /* incr exp */ + } + } return; } @@ -679,59 +679,60 @@ void vax_hmul (UFPH *a, UFPH *b) int32 i; UQP accum = { 0, 0, 0, 0 }; -if ((a->exp == 0) || (b->exp == 0)) { /* zero argument? */ - a->frac.f0 = a->frac.f1 = 0; /* result is zero */ - a->frac.f2 = a->frac.f3 = 0; - a->sign = a->exp = 0; - return; - } -a->sign = a->sign ^ b->sign; /* sign of result */ -a->exp = a->exp + b->exp - H_BIAS; /* add exponents */ -for (i = 0; i < 128; i++) { /* quad precision */ - qp_rsh (&accum, 1); /* shift result */ - if (a->frac.f0 & 1) qp_add (&accum, &b->frac); /* mplr low? add */ - qp_rsh (&a->frac, 1); /* shift mplr */ - } -a->frac = accum; /* result */ -h_normh (a); /* normalize */ +if ((a->exp == 0) || (b->exp == 0)) { /* zero argument? */ + a->frac.f0 = a->frac.f1 = 0; /* result is zero */ + a->frac.f2 = a->frac.f3 = 0; + a->sign = a->exp = 0; + return; + } +a->sign = a->sign ^ b->sign; /* sign of result */ +a->exp = a->exp + b->exp - H_BIAS; /* add exponents */ +for (i = 0; i < 128; i++) { /* quad precision */ + qp_rsh (&accum, 1); /* shift result */ + if (a->frac.f0 & 1) qp_add (&accum, &b->frac); /* mplr low? add */ + qp_rsh (&a->frac, 1); /* shift mplr */ + } +a->frac = accum; /* result */ +h_normh (a); /* normalize */ return; } /* Floating modulus - there are three cases - exp <= bias - integer is 0, fraction is input, - no overflow - bias < exp <= bias+128 - separate integer and fraction, - integer overflow may occur - bias+128 < exp - result is integer, fraction is 0 - integer overflow + exp <= bias - integer is 0, fraction is input, + no overflow + bias < exp <= bias+128 - separate integer and fraction, + integer overflow may occur + bias+128 < exp - result is integer, fraction is 0 + integer overflow */ void vax_hmod (UFPH *a, int32 *intgr, int32 *flg) { UQP ifr; -if (a->exp <= H_BIAS) *intgr = *flg = 0; /* 0 or <1? int = 0 */ -else if (a->exp <= (H_BIAS + 128)) { /* in range? */ - ifr = a->frac; - qp_rsh (&ifr, 128 - (a->exp - H_BIAS)); /* separate integer */ - if ((a->exp > (H_BIAS + 32)) || /* test ovflo */ - ((a->exp == (H_BIAS + 32)) && - (ifr.f0 > (a->sign? 0x80000000: 0x7FFFFFFF)))) - *flg = CC_V; - else *flg = 0; - *intgr = ifr.f0; - if (a->sign) *intgr = -*intgr; /* -? comp int */ - qp_lsh (&a->frac, a->exp - H_BIAS); /* excise integer */ - a->exp = H_BIAS; - } -else { *intgr = 0; /* out of range */ - a->frac.f0 = a->frac.f1 = 0; /* result 0 */ - a->frac.f2 = a->frac.f3 = 0; - a->sign = a->exp = 0; - *flg = CC_V; /* overflow */ - } -h_normh (a); /* normalize */ +if (a->exp <= H_BIAS) *intgr = *flg = 0; /* 0 or <1? int = 0 */ +else if (a->exp <= (H_BIAS + 128)) { /* in range? */ + ifr = a->frac; + qp_rsh (&ifr, 128 - (a->exp - H_BIAS)); /* separate integer */ + if ((a->exp > (H_BIAS + 32)) || /* test ovflo */ + ((a->exp == (H_BIAS + 32)) && + (ifr.f0 > (a->sign? 0x80000000: 0x7FFFFFFF)))) + *flg = CC_V; + else *flg = 0; + *intgr = ifr.f0; + if (a->sign) *intgr = -*intgr; /* -? comp int */ + qp_lsh (&a->frac, a->exp - H_BIAS); /* excise integer */ + a->exp = H_BIAS; + } +else { + *intgr = 0; /* out of range */ + a->frac.f0 = a->frac.f1 = 0; /* result 0 */ + a->frac.f2 = a->frac.f3 = 0; + a->sign = a->exp = 0; + *flg = CC_V; /* overflow */ + } +h_normh (a); /* normalize */ return; } @@ -744,58 +745,58 @@ void vax_hdiv (UFPH *a, UFPH *b) int32 i; UQP ndvr, quo = { 0, 0, 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 + H_BIAS + 1; /* unbiased exp */ -qp_rsh (&a->frac, 1); /* allow 1 bit left */ +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 + H_BIAS + 1; /* unbiased exp */ +qp_rsh (&a->frac, 1); /* allow 1 bit left */ qp_rsh (&b->frac, 1); -ndvr = a->frac; /* copy divisor */ -qp_neg (&ndvr); /* and negate */ -for (i = 0; i < 128; i++) { /* divide loop */ - qp_lsh (&quo, 1); /* shift quo */ - if (qp_cmp (&b->frac, &a->frac) >= 0) { /* div step ok? */ - qp_add (&b->frac, &ndvr); /* "subtract" */ - quo.f0 = quo.f0 + 1; /* quo bit = 1 */ - } - qp_lsh (&b->frac, 1); /* shift divd */ - } +ndvr = a->frac; /* copy divisor */ +qp_neg (&ndvr); /* and negate */ +for (i = 0; i < 128; i++) { /* divide loop */ + qp_lsh (&quo, 1); /* shift quo */ + if (qp_cmp (&b->frac, &a->frac) >= 0) { /* div step ok? */ + qp_add (&b->frac, &ndvr); /* "subtract" */ + quo.f0 = quo.f0 + 1; /* quo bit = 1 */ + } + qp_lsh (&b->frac, 1); /* shift divd */ + } b->frac = quo; -h_normh (b); /* normalize */ +h_normh (b); /* normalize */ return; } - + /* Quad precision integer routines */ int32 qp_cmp (UQP *a, UQP *b) { -if (a->f3 < b->f3) return -1; /* compare hi */ +if (a->f3 < b->f3) return -1; /* compare hi */ if (a->f3 > b->f3) return +1; -if (a->f2 < b->f2) return -1; /* hi =, compare mid1 */ +if (a->f2 < b->f2) return -1; /* hi =, compare mid1 */ if (a->f2 > b->f2) return +1; -if (a->f1 < b->f1) return -1; /* mid1 =, compare mid2 */ +if (a->f1 < b->f1) return -1; /* mid1 =, compare mid2 */ if (a->f1 > b->f1) return +1; -if (a->f0 < b->f0) return -1; /* mid2 =, compare lo */ +if (a->f0 < b->f0) return -1; /* mid2 =, compare lo */ if (a->f0 > b->f0) return +1; -return 0; /* all equal */ +return 0; /* all equal */ } void qp_add (UQP *a, UQP *b) { -a->f0 = (a->f0 + b->f0) & LMASK; /* add lo */ -if (a->f0 < b->f0) a->f1 = a->f1 + 1; /* carry? */ -a->f1 = (a->f1 + b->f1) & LMASK; /* add mid2 */ -if (a->f1 < b->f1) a->f2 = a->f2 + 1; /* carry? */ -a->f2 = (a->f2 + b->f2) & LMASK; /* add mid1 */ -if (a->f2 < b->f2) a->f3 = a->f3 + 1; /* carry? */ -a->f3 = (a->f3 + b->f3) & LMASK; /* add hi */ +a->f0 = (a->f0 + b->f0) & LMASK; /* add lo */ +if (a->f0 < b->f0) a->f1 = a->f1 + 1; /* carry? */ +a->f1 = (a->f1 + b->f1) & LMASK; /* add mid2 */ +if (a->f1 < b->f1) a->f2 = a->f2 + 1; /* carry? */ +a->f2 = (a->f2 + b->f2) & LMASK; /* add mid1 */ +if (a->f2 < b->f2) a->f3 = a->f3 + 1; /* carry? */ +a->f3 = (a->f3 + b->f3) & LMASK; /* add hi */ return; } void qp_inc (UQP *a) { -a->f0 = (a->f0 + 1) & LMASK; /* inc lo */ -if (a->f0 == 0) a->f1 = (a->f1 + 1) & LMASK; /* propagate carry */ +a->f0 = (a->f0 + 1) & LMASK; /* inc lo */ +if (a->f0 == 0) a->f1 = (a->f1 + 1) & LMASK; /* propagate carry */ if (a->f1 == 0) a->f2 = (a->f2 + 1) & LMASK; if (a->f2 == 0) a->f3 = (a->f3 + 1) & LMASK; return; @@ -803,119 +804,119 @@ return; void qp_neg (UQP *r) { -r->f0 = NEG (r->f0); /* neg lo */ -r->f1 = (~r->f1 + (r->f0 == 0)) & LMASK; /* complement rest */ -r->f2 = (~r->f2 + (r->f1 == 0)) & LMASK; /* propagate carry */ +r->f0 = NEG (r->f0); /* neg lo */ +r->f1 = (~r->f1 + (r->f0 == 0)) & LMASK; /* complement rest */ +r->f2 = (~r->f2 + (r->f1 == 0)) & LMASK; /* propagate carry */ r->f3 = (~r->f3 + (r->f2 == 0)) & LMASK; return; } void qp_lsh (UQP *r, uint32 sc) { -if (sc >= 128) r->f3 = r->f2 = r->f1 = r->f0 = 0; /* > 127? result 0 */ -else if (sc >= 96) { /* [96,127]? */ - r->f3 = (r->f0 << (sc - 96)) & LMASK; - r->f2 = r->f1 = r->f0 = 0; - } -else if (sc > 64) { /* [65,95]? */ - r->f3 = ((r->f1 << (sc - 64)) | (r->f0 >> (96 - sc))) & LMASK; - r->f2 = (r->f0 << (sc - 64)) & LMASK; - r->f1 = r->f0 = 0; - } -else if (sc == 64) { /* [64]? */ - r->f3 = r->f1; - r->f2 = r->f0; - r->f1 = r->f0 = 0; - } -else if (sc > 32) { /* [33,63]? */ - r->f3 = ((r->f2 << (sc - 32)) | (r->f1 >> (64 - sc))) & LMASK; - r->f2 = ((r->f1 << (sc - 32)) | (r->f0 >> (64 - sc))) & LMASK; - r->f1 = (r->f0 << (sc - 32)) & LMASK; - r->f0 = 0; - } -else if (sc == 32) { /* [32]? */ - r->f3 = r->f2; - r->f2 = r->f1; - r->f1 = r->f0; - r->f0 = 0; - } -else if (sc != 0) { /* [31,1]? */ - r->f3 = ((r->f3 << sc) | (r->f2 >> (32 - sc))) & LMASK; - r->f2 = ((r->f2 << sc) | (r->f1 >> (32 - sc))) & LMASK; - r->f1 = ((r->f1 << sc) | (r->f0 >> (32 - sc))) & LMASK; - r->f0 = (r->f0 << sc) & LMASK; - } +if (sc >= 128) r->f3 = r->f2 = r->f1 = r->f0 = 0; /* > 127? result 0 */ +else if (sc >= 96) { /* [96,127]? */ + r->f3 = (r->f0 << (sc - 96)) & LMASK; + r->f2 = r->f1 = r->f0 = 0; + } +else if (sc > 64) { /* [65,95]? */ + r->f3 = ((r->f1 << (sc - 64)) | (r->f0 >> (96 - sc))) & LMASK; + r->f2 = (r->f0 << (sc - 64)) & LMASK; + r->f1 = r->f0 = 0; + } +else if (sc == 64) { /* [64]? */ + r->f3 = r->f1; + r->f2 = r->f0; + r->f1 = r->f0 = 0; + } +else if (sc > 32) { /* [33,63]? */ + r->f3 = ((r->f2 << (sc - 32)) | (r->f1 >> (64 - sc))) & LMASK; + r->f2 = ((r->f1 << (sc - 32)) | (r->f0 >> (64 - sc))) & LMASK; + r->f1 = (r->f0 << (sc - 32)) & LMASK; + r->f0 = 0; + } +else if (sc == 32) { /* [32]? */ + r->f3 = r->f2; + r->f2 = r->f1; + r->f1 = r->f0; + r->f0 = 0; + } +else if (sc != 0) { /* [31,1]? */ + r->f3 = ((r->f3 << sc) | (r->f2 >> (32 - sc))) & LMASK; + r->f2 = ((r->f2 << sc) | (r->f1 >> (32 - sc))) & LMASK; + r->f1 = ((r->f1 << sc) | (r->f0 >> (32 - sc))) & LMASK; + r->f0 = (r->f0 << sc) & LMASK; + } return; } void qp_rsh (UQP *r, uint32 sc) { -if (sc >= 128) r->f3 = r->f2 = r->f1 = r->f0 = 0; /* > 127? result 0 */ -else if (sc >= 96) { /* [96,127]? */ - r->f0 = (r->f3 >> (sc - 96)) & LMASK; - r->f1 = r->f2 = r->f3 = 0; - } -else if (sc > 64) { /* [65,95]? */ - r->f0 = ((r->f2 >> (sc - 64)) | (r->f3 << (96 - sc))) & LMASK; - r->f1 = (r->f3 >> (sc - 64)) & LMASK; - r->f2 = r->f3 = 0; - } -else if (sc == 64) { /* [64]? */ - r->f0 = r->f2; - r->f1 = r->f3; - r->f2 = r->f3 = 0; - } -else if (sc > 32) { /* [33,63]? */ - r->f0 = ((r->f1 >> (sc - 32)) | (r->f2 << (64 - sc))) & LMASK; - r->f1 = ((r->f2 >> (sc - 32)) | (r->f3 << (64 - sc))) & LMASK; - r->f2 = (r->f3 >> (sc - 32)) & LMASK; - r->f3 = 0; - } -else if (sc == 32) { /* [32]? */ - r->f0 = r->f1; - r->f1 = r->f2; - r->f2 = r->f3; - r->f3 = 0; - } -else if (sc != 0) { /* [31,1]? */ - r->f0 = ((r->f0 >> sc) | (r->f1 << (32 - sc))) & LMASK; - r->f1 = ((r->f1 >> sc) | (r->f2 << (32 - sc))) & LMASK; - r->f2 = ((r->f2 >> sc) | (r->f3 << (32 - sc))) & LMASK; - r->f3 = (r->f3 >> sc) & LMASK; - } +if (sc >= 128) r->f3 = r->f2 = r->f1 = r->f0 = 0; /* > 127? result 0 */ +else if (sc >= 96) { /* [96,127]? */ + r->f0 = (r->f3 >> (sc - 96)) & LMASK; + r->f1 = r->f2 = r->f3 = 0; + } +else if (sc > 64) { /* [65,95]? */ + r->f0 = ((r->f2 >> (sc - 64)) | (r->f3 << (96 - sc))) & LMASK; + r->f1 = (r->f3 >> (sc - 64)) & LMASK; + r->f2 = r->f3 = 0; + } +else if (sc == 64) { /* [64]? */ + r->f0 = r->f2; + r->f1 = r->f3; + r->f2 = r->f3 = 0; + } +else if (sc > 32) { /* [33,63]? */ + r->f0 = ((r->f1 >> (sc - 32)) | (r->f2 << (64 - sc))) & LMASK; + r->f1 = ((r->f2 >> (sc - 32)) | (r->f3 << (64 - sc))) & LMASK; + r->f2 = (r->f3 >> (sc - 32)) & LMASK; + r->f3 = 0; + } +else if (sc == 32) { /* [32]? */ + r->f0 = r->f1; + r->f1 = r->f2; + r->f2 = r->f3; + r->f3 = 0; + } +else if (sc != 0) { /* [31,1]? */ + r->f0 = ((r->f0 >> sc) | (r->f1 << (32 - sc))) & LMASK; + r->f1 = ((r->f1 >> sc) | (r->f2 << (32 - sc))) & LMASK; + r->f2 = ((r->f2 >> sc) | (r->f3 << (32 - sc))) & LMASK; + r->f3 = (r->f3 >> sc) & LMASK; + } return; } void qp_rsh_s (UQP *r, uint32 sc, uint32 neg) { -qp_rsh (r, sc); /* do unsigned right */ -if (neg && sc) { /* negative? */ - if (sc >= 128) - r->f0 = r->f1 = r->f2 = r->f3 = LMASK; /* > 127? result -1 */ - else { - UQP ones = { LMASK, LMASK, LMASK, LMASK }; - qp_lsh (&ones, 128 - sc); /* shift ones */ - r->f0 = r->f0 | ones.f0; /* or into result */ - r->f1 = r->f1 | ones.f1; - r->f2 = r->f2 | ones.f2; - r->f3 = r->f3 | ones.f3; - } - } +qp_rsh (r, sc); /* do unsigned right */ +if (neg && sc) { /* negative? */ + if (sc >= 128) + r->f0 = r->f1 = r->f2 = r->f3 = LMASK; /* > 127? result -1 */ + else { + UQP ones = { LMASK, LMASK, LMASK, LMASK }; + qp_lsh (&ones, 128 - sc); /* shift ones */ + r->f0 = r->f0 | ones.f0; /* or into result */ + r->f1 = r->f1 | ones.f1; + r->f2 = r->f2 | ones.f2; + r->f3 = r->f3 | ones.f3; + } + } return; } - + /* Support routines */ void h_unpackfd (int32 hi, int32 lo, UFPH *r) { -r->sign = hi & FPSIGN; /* get sign */ -r->exp = FD_GETEXP (hi); /* get exponent */ -r->frac.f0 = r->frac.f1 = 0; /* low bits 0 */ -if (r->exp == 0) { /* exp = 0? */ - if (r->sign) RSVD_OPND_FAULT; /* if -, rsvd op */ - r->frac.f2 = r->frac.f3 = 0; /* else 0 */ - return; - } +r->sign = hi & FPSIGN; /* get sign */ +r->exp = FD_GETEXP (hi); /* get exponent */ +r->frac.f0 = r->frac.f1 = 0; /* low bits 0 */ +if (r->exp == 0) { /* exp = 0? */ + if (r->sign) RSVD_OPND_FAULT; /* if -, rsvd op */ + r->frac.f2 = r->frac.f3 = 0; /* else 0 */ + return; + } r->frac.f3 = WORDSWAP ((hi & ~(FPSIGN | FD_EXP)) | FD_HB); r->frac.f2 = WORDSWAP (lo); qp_lsh (&r->frac, FD_GUARD); @@ -924,14 +925,14 @@ return; void h_unpackg (int32 hi, int32 lo, UFPH *r) { -r->sign = hi & FPSIGN; /* get sign */ -r->exp = G_GETEXP (hi); /* get exponent */ -r->frac.f0 = r->frac.f1 = 0; /* low bits 0 */ -if (r->exp == 0) { /* exp = 0? */ - if (r->sign) RSVD_OPND_FAULT; /* if -, rsvd op */ - r->frac.f2 = r->frac.f3 = 0; /* else 0 */ - return; - } +r->sign = hi & FPSIGN; /* get sign */ +r->exp = G_GETEXP (hi); /* get exponent */ +r->frac.f0 = r->frac.f1 = 0; /* low bits 0 */ +if (r->exp == 0) { /* exp = 0? */ + if (r->sign) RSVD_OPND_FAULT; /* if -, rsvd op */ + r->frac.f2 = r->frac.f3 = 0; /* else 0 */ + return; + } r->frac.f3 = WORDSWAP ((hi & ~(FPSIGN | G_EXP)) | G_HB); r->frac.f2 = WORDSWAP (lo); qp_lsh (&r->frac, G_GUARD); @@ -940,14 +941,14 @@ return; void h_unpackh (int32 *hflt, UFPH *r) { -r->sign = hflt[0] & FPSIGN; /* get sign */ -r->exp = H_GETEXP (hflt[0]); /* get exponent */ -if (r->exp == 0) { /* exp = 0? */ - if (r->sign) RSVD_OPND_FAULT; /* if -, rsvd op */ - r->frac.f0 = r->frac.f1 = 0; /* else 0 */ - r->frac.f2 = r->frac.f3 = 0; - return; - } +r->sign = hflt[0] & FPSIGN; /* get sign */ +r->exp = H_GETEXP (hflt[0]); /* get exponent */ +if (r->exp == 0) { /* exp = 0? */ + if (r->sign) RSVD_OPND_FAULT; /* if -, rsvd op */ + r->frac.f0 = r->frac.f1 = 0; /* else 0 */ + r->frac.f2 = r->frac.f3 = 0; + return; + } r->frac.f3 = WORDSWAP ((hflt[0] & ~(FPSIGN | H_EXP)) | H_HB); r->frac.f2 = WORDSWAP (hflt[1]); r->frac.f1 = WORDSWAP (hflt[2]); @@ -964,98 +965,99 @@ static uint32 normmask[5] = { static int32 normtab[6] = { 1, 2, 4, 8, 16, 32}; if ((r->frac.f0 == 0) && (r->frac.f1 == 0) && - (r->frac.f2 == 0) && (r->frac.f3 == 0)) { /* if fraction = 0 */ - r->sign = r->exp = 0; /* result is 0 */ - return; - } -while ((r->frac.f3 & UH_NM_H) == 0) { /* normalized? */ - for (i = 0; i < 5; i++) { /* find first 1 */ - if (r->frac.f3 & normmask[i]) break; - } - qp_lsh (&r->frac, normtab[i]); /* shift frac */ - r->exp = r->exp - normtab[i]; /* decr exp */ - } + (r->frac.f2 == 0) && (r->frac.f3 == 0)) { /* if fraction = 0 */ + r->sign = r->exp = 0; /* result is 0 */ + return; + } +while ((r->frac.f3 & UH_NM_H) == 0) { /* normalized? */ + for (i = 0; i < 5; i++) { /* find first 1 */ + if (r->frac.f3 & normmask[i]) break; + } + qp_lsh (&r->frac, normtab[i]); /* shift frac */ + r->exp = r->exp - normtab[i]; /* decr exp */ + } return; } - + int32 h_rpackfd (UFPH *r, int32 *rh) { static UQP f_round = { 0, 0, 0, UH_FRND }; static UQP d_round = { 0, 0, UH_DRND, 0 }; -if (rh) *rh = 0; /* assume 0 */ -if (r->exp == 0) return 0; /* exp = 0? done */ +if (rh) *rh = 0; /* assume 0 */ +if (r->exp == 0) return 0; /* exp = 0? done */ qp_add (&r->frac, rh? &d_round: &f_round); -if ((r->frac.f3 & UH_NM_H) == 0) { /* carry out? */ - qp_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 */ - } -qp_rsh (&r->frac, FD_GUARD); /* remove guard */ +if ((r->frac.f3 & UH_NM_H) == 0) { /* carry out? */ + qp_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 */ + } +qp_rsh (&r->frac, FD_GUARD); /* remove guard */ if (rh) *rh = WORDSWAP (r->frac.f2); return r->sign | (r->exp << FD_V_EXP) | - (WORDSWAP (r->frac.f3) & ~(FD_HB | FPSIGN | FD_EXP)); + (WORDSWAP (r->frac.f3) & ~(FD_HB | FPSIGN | FD_EXP)); } int32 h_rpackg (UFPH *r, int32 *rh) { static UQP g_round = { 0, 0, UH_GRND, 0 }; -*rh = 0; /* assume 0 */ -if (r->exp == 0) return 0; /* exp = 0? done */ -qp_add (&r->frac, &g_round); /* round */ -if ((r->frac.f3 & UH_NM_H) == 0) { /* carry out? */ - qp_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 */ - } -qp_rsh (&r->frac, G_GUARD); /* remove guard */ -*rh = WORDSWAP (r->frac.f2); /* get low */ +*rh = 0; /* assume 0 */ +if (r->exp == 0) return 0; /* exp = 0? done */ +qp_add (&r->frac, &g_round); /* round */ +if ((r->frac.f3 & UH_NM_H) == 0) { /* carry out? */ + qp_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 */ + } +qp_rsh (&r->frac, G_GUARD); /* remove guard */ +*rh = WORDSWAP (r->frac.f2); /* get low */ return r->sign | (r->exp << G_V_EXP) | - (WORDSWAP (r->frac.f3) & ~(G_HB | FPSIGN | G_EXP)); + (WORDSWAP (r->frac.f3) & ~(G_HB | FPSIGN | G_EXP)); } int32 h_rpackh (UFPH *r, int32 *hflt) { static UQP h_round = { UH_HRND, 0, 0, 0 }; -hflt[0] = hflt[1] = hflt[2] = hflt[3] = 0; /* assume 0 */ -if (r->exp == 0) return 0; /* exp = 0? done */ -qp_add (&r->frac, &h_round); /* round */ -if ((r->frac.f3 & UH_NM_H) == 0) { /* carry out? */ - qp_rsh (&r->frac, 1); /* renormalize */ - r->exp = r->exp + 1; - } -if (r->exp > (int32) H_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 */ - } -qp_rsh (&r->frac, H_GUARD); /* remove guard */ +hflt[0] = hflt[1] = hflt[2] = hflt[3] = 0; /* assume 0 */ +if (r->exp == 0) return 0; /* exp = 0? done */ +qp_add (&r->frac, &h_round); /* round */ +if ((r->frac.f3 & UH_NM_H) == 0) { /* carry out? */ + qp_rsh (&r->frac, 1); /* renormalize */ + r->exp = r->exp + 1; + } +if (r->exp > (int32) H_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 */ + } +qp_rsh (&r->frac, H_GUARD); /* remove guard */ hflt[0] = r->sign | (r->exp << H_V_EXP) | - (WORDSWAP (r->frac.f3) & ~(H_HB | FPSIGN | H_EXP)); + (WORDSWAP (r->frac.f3) & ~(H_HB | FPSIGN | H_EXP)); hflt[1] = WORDSWAP (r->frac.f2); hflt[2] = WORDSWAP (r->frac.f1); hflt[3] = WORDSWAP (r->frac.f0); return hflt[0]; } - + void h_write_b (int32 spec, int32 va, int32 val, int32 acc) { int32 rn; if (spec > (GRN | nPC)) Write (va, val, L_BYTE, WA); -else { rn = spec & 0xF; - R[rn] = (R[rn] & ~BMASK) | val; - } +else { + rn = spec & 0xF; + R[rn] = (R[rn] & ~BMASK) | val; + } return; } @@ -1064,9 +1066,10 @@ void h_write_w (int32 spec, int32 va, int32 val, int32 acc) int32 rn; if (spec > (GRN | nPC)) Write (va, val, L_WORD, WA); -else { rn = spec & 0xF; - R[rn] = (R[rn] & ~WMASK) | val; - } +else { + rn = spec & 0xF; + R[rn] = (R[rn] & ~WMASK) | val; + } return; } @@ -1082,15 +1085,16 @@ void h_write_q (int32 spec, int32 va, int32 vl, int32 vh, int32 acc) int32 rn, mstat; if (spec > (GRN | nPC)) { - if (Test (va + 7, WA, &mstat) >= 0) - Write (va, vl, L_LONG, WA); - Write (va + 4, vh, L_LONG, WA); - } -else { rn = spec & 0xF; - if (rn >= nSP) RSVD_ADDR_FAULT; - R[rn] = vl; - R[rn + 1] = vh; - } + if (Test (va + 7, WA, &mstat) >= 0) + Write (va, vl, L_LONG, WA); + Write (va + 4, vh, L_LONG, WA); + } +else { + rn = spec & 0xF; + if (rn >= nSP) RSVD_ADDR_FAULT; + R[rn] = vl; + R[rn + 1] = vh; + } return; } @@ -1099,22 +1103,23 @@ void h_write_o (int32 spec, int32 va, int32 *val, int32 acc) int32 rn, mstat; if (spec > (GRN | nPC)) { - if (Test (va + 15, WA, &mstat) >= 0) - Write (va, val[0], L_LONG, WA); - Write (va + 4, val[1], L_LONG, WA); - Write (va + 8, val[2], L_LONG, WA); - Write (va + 12, val[3], L_LONG, WA); - } -else { rn = spec & 0xF; - if (rn >= nAP) RSVD_ADDR_FAULT; - R[rn] = val[0]; - R[rn + 1] = val[1]; - R[rn + 2] = val[2]; - R[rn + 3] = val[3]; - } + if (Test (va + 15, WA, &mstat) >= 0) + Write (va, val[0], L_LONG, WA); + Write (va + 4, val[1], L_LONG, WA); + Write (va + 8, val[2], L_LONG, WA); + Write (va + 12, val[3], L_LONG, WA); + } +else { + rn = spec & 0xF; + if (rn >= nAP) RSVD_ADDR_FAULT; + R[rn] = val[0]; + R[rn + 1] = val[1]; + R[rn + 2] = val[2]; + R[rn + 3] = val[3]; + } return; } - + #else extern jmp_buf save_env; diff --git a/VAX/vax_stddev.c b/VAX/vax_stddev.c index 39fa53dd..3fcd0a71 100644 --- a/VAX/vax_stddev.c +++ b/VAX/vax_stddev.c @@ -1,6 +1,6 @@ /* vax_stddev.c: VAX 3900 standard I/O devices - Copyright (c) 1998-2004, Robert M Supnik + Copyright (c) 1998-2005, 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"), @@ -19,57 +19,57 @@ 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 + 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 + tti terminal input + tto terminal output + clk 100Hz and TODR clock - 09-Sep-04 RMS Integrated powerup into RESET (with -p) - 28-May-04 RMS Removed SET TTI CTRL-C - 29-Dec-03 RMS Added console backpressure support - 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 + 09-Sep-04 RMS Integrated powerup into RESET (with -p) + 28-May-04 RMS Removed SET TTI CTRL-C + 29-Dec-03 RMS Added console backpressure support + 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 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) +#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; extern int32 sim_switches; -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 */ +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); @@ -79,12 +79,12 @@ t_stat tto_reset (DEVICE *dptr); t_stat clk_reset (DEVICE *dptr); extern int32 sysd_hlt_enb (void); - + /* TTI data structures - tti_dev TTI device descriptor - tti_unit TTI unit descriptor - tti_reg TTI register list + 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 } }; @@ -92,34 +92,37 @@ 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 } }; + { 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, 0, "VECTOR", NULL, - NULL, &show_vec, NULL }, - { 0 } }; + { UNIT_8B, UNIT_8B, "8b", "8B", NULL }, + { UNIT_8B, 0 , "7b", "7B", 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 }; + "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 + 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 } }; @@ -127,33 +130,36 @@ 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 } }; + { 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 } }; + { 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 }; - + "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 + 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 } }; @@ -161,34 +167,37 @@ 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 } }; + { 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 } }; + { 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 }; - + "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 + 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) @@ -208,10 +217,10 @@ return (tti_csr & TTICSR_IMP); int32 rxdb_rd (void) { -int32 t = tti_unit.buf; /* char + error */ +int32 t = tti_unit.buf; /* char + error */ -tti_csr = tti_csr & ~CSR_DONE; /* clr done */ -tti_unit.buf = tti_unit.buf & 0377; /* clr errors */ +tti_csr = tti_csr & ~CSR_DONE; /* clr done */ +tti_unit.buf = tti_unit.buf & 0377; /* clr errors */ CLR_INT (TTI); return t; } @@ -239,7 +248,7 @@ 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); + SET_INT (TTI); tti_csr = (tti_csr & ~TTICSR_RW) | (data & TTICSR_RW); return; } @@ -248,7 +257,7 @@ 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); + SET_INT (TTO); tto_csr = (tto_csr & ~TTOCSR_RW) | (data & TTOCSR_RW); return; } @@ -261,22 +270,23 @@ CLR_INT (TTO); sim_activate (&tto_unit, tto_unit.wait); return; } - + /* Terminal input routines - tti_svc process event (character ready) - tti_reset process reset + 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; } +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; @@ -289,14 +299,14 @@ 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 */ +sim_activate (&tti_unit, tti_unit.wait); /* activate unit */ return SCPE_OK; } - + /* Terminal output routines - tto_svc process event (character typed) - tto_reset process reset + tto_svc process event (character typed) + tto_reset process reset */ t_stat tto_svc (UNIT *uptr) @@ -305,9 +315,10 @@ int32 c; t_stat r; c = tto_unit.buf & ((tto_unit.flags & UNIT_8B)? 0377: 0177); -if ((r = sim_putchar_s (c)) != SCPE_OK) { /* output; error? */ - sim_activate (uptr, uptr->wait); /* retry */ - return ((r == SCPE_STALL)? SCPE_OK: r); } /* !stall? report */ +if ((r = sim_putchar_s (c)) != SCPE_OK) { /* output; error? */ + sim_activate (uptr, uptr->wait); /* retry */ + return ((r == SCPE_STALL)? SCPE_OK: r); /* !stall? report */ + } tto_csr = tto_csr | CSR_DONE; if (tto_csr & CSR_IE) SET_INT (TTO); tto_unit.pos = tto_unit.pos + 1; @@ -319,15 +330,15 @@ t_stat tto_reset (DEVICE *dptr) tto_unit.buf = 0; tto_csr = CSR_DONE; CLR_INT (TTO); -sim_cancel (&tto_unit); /* deactivate unit */ +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) + 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) @@ -335,11 +346,11 @@ 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 */ +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; } @@ -349,15 +360,15 @@ 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 */ +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; } @@ -366,13 +377,13 @@ t_stat clk_reset (DEVICE *dptr) { int32 t; -if (sim_switches & SWMASK ('P')) todr_powerup (); /* powerup? */ +if (sim_switches & SWMASK ('P')) todr_powerup (); /* powerup? */ 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 */ +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; } diff --git a/VAX/vax_sys.c b/VAX/vax_sys.c index 01c1d34d..8b363f0e 100644 --- a/VAX/vax_sys.c +++ b/VAX/vax_sys.c @@ -1,6 +1,6 @@ /* vax_sys.c: VAX simulator interface - Copyright (c) 1998-2004, Robert M Supnik + Copyright (c) 1998-2005, 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"), @@ -19,33 +19,35 @@ 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 + 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-Sep-04 RMS Fixed bugs in character display and parse - 30-Sep-04 RMS Fixed bugs in parsing indirect displacement modes - Added compatibility mode support - 04-Sep-04 RMS Added octa instruction support - 02-Sep-04 RMS Fixed parse branch return status - 13-Jul-04 RMS Fixed bad block routine - 16-Jun-04 RMS Added DHQ11 support - 21-Mar-04 RMS Added RXV21 support - 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 + 04-Sep-05 RMS Fixed missing assignment (found by Peter Schorn) + 16-Aug-05 RMS Fixed C++ declaration and cast problems + 15-Sep-04 RMS Fixed bugs in character display and parse + 30-Sep-04 RMS Fixed bugs in parsing indirect displacement modes + Added compatibility mode support + 04-Sep-04 RMS Added octa instruction support + 02-Sep-04 RMS Fixed parse branch return status + 13-Jul-04 RMS Fixed bad block routine + 16-Jun-04 RMS Added DHQ11 support + 21-Mar-04 RMS Added RXV21 support + 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 #if defined (FULL_VAX) -#define ODC(x) (x) +#define ODC(x) (x) #else -#define ODC(x) ((x) << DR_V_USPMASK) +#define ODC(x) ((x) << DR_V_USPMASK) #endif extern UNIT cpu_unit; @@ -59,24 +61,24 @@ int32 fprint_sym_qoimm (FILE *of, t_value *val, int32 vp, int32 lnt); t_stat parse_char (char *cptr, t_value *val, 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 vp, int32 lnt, t_stat *r); int32 parse_spec (char *cptr, uint32 addr, t_value *val, - int32 vp, int32 disp, t_stat *r); + 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); + int lnt, int32 minus); extern t_stat fprint_sym_cm (FILE *of, t_addr addr, t_value *bytes, int32 sw); t_stat parse_sym_cm (char *cptr, t_addr addr, t_value *bytes, int32 sw); /* 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 + 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 */ REG *sim_PC = &cpu_reg[0]; @@ -84,37 +86,38 @@ REG *sim_PC = &cpu_reg[0]; int32 sim_emax = 60; 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" }; - + "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" + }; + /* 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) + 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 + uptr = pointer to unit + sec = number of sectors per surface + wds = number of words per sector Outputs: - sta = status code + sta = status code */ t_stat pdp11_bad_block (UNIT *uptr, int32 sec, int32 wds) @@ -128,540 +131,541 @@ if ((uptr->flags & UNIT_ATT) == 0) return SCPE_UNATT; if (!get_yn ("Overwrite last track? [N]", FALSE)) return SCPE_OK; da = (uptr->capac - (sec * wds)) * sizeof (uint16); if (sim_fseek (uptr->fileref, da, SEEK_SET)) return SCPE_IOERR; -if ((buf = malloc (wds * sizeof (uint16))) == NULL) return SCPE_MEM; +if ((buf = (uint16 *) malloc (wds * sizeof (uint16))) == NULL) return SCPE_MEM; buf[0] = 0x1234; buf[1] = 0x5678; buf[2] = buf[3] = 0; for (i = 4; i < wds; i++) buf[i] = 0xFFFF; for (i = 0; (i < sec) && (i < 10); i++) - sim_fwrite (buf, sizeof (uint16), wds, uptr->fileref); + sim_fwrite (buf, sizeof (uint16), 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> + - 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, -ODC(2), RD, WO, 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 */ -ODC(2), RG, WO, 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 */ -ODC(2), RH, MO, 0, 0, 0, 0, /* ADDH2 */ -ODC(3), RH, RH, WO, 0, 0, 0, /* ADDH3 */ -ODC(2), RH, MO, 0, 0, 0, 0, /* SUBH2 */ -ODC(3), RH, RH, WO, 0, 0, 0, /* SUBH3 */ -ODC(2), RH, MO, 0, 0, 0, 0, /* MULH2 */ -ODC(3), RH, RH, WO, 0, 0, 0, /* MULH3 */ -ODC(2), RH, MO, 0, 0, 0, 0, /* DIVH2 */ -ODC(3), RH, RH, WO, 0, 0, 0, /* DIVH3 */ -ODC(2), RH, WB, 0, 0, 0, 0, /* CVTHB */ -ODC(2), RH, WW, 0, 0, 0, 0, /* CVTHW */ -ODC(2), RH, WL, 0, 0, 0, 0, /* CVTHL */ -ODC(2), RH, WL, 0, 0, 0, 0, /* CVTRHL */ -ODC(2), RB, WO, 0, 0, 0, 0, /* CVTBH */ -ODC(2), RW, WO, 0, 0, 0, 0, /* CVTWH */ -ODC(2), RL, WO, 0, 0, 0, 0, /* CVTLH */ -ODC(4), RH, RH, MO, BW, 0, 0, /* ACBH */ -ODC(2), RH, RO, 0, 0, 0, 0, /* MOVH */ -ODC(2), RH, RH, 0, 0, 0, 0, /* CMPH */ -ODC(2), RH, WO, 0, 0, 0, 0, /* MNEGH */ -ODC(1), RH, 0, 0, 0, 0, 0, /* TSTH */ -ODC(5), RH, RW, RH, WL, WO, 0, /* EMODH */ -ODC(3), RH, RW, AB, 0, 0, 0, /* POLYH */ -ODC(2), RH, 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 */ -ODC(1), WO, 0, 0, 0, 0, 0, /* CLRO */ -ODC(2), RO, RO, 0, 0, 0, 0, /* MOVO */ -ODC(2), AO, WL, 0, 0, 0, 0, /* MOVAO*/ -ODC(1), AO, 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, -ODC(2), RF, WO, 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, -ODC(2), RH, WL, 0, 0, 0, 0, /* CVTHF */ -ODC(2), RH, 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 }; - +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, +ODC(2), RD, WO, 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 */ +ODC(2), RG, WO, 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 */ +ODC(2), RH, MO, 0, 0, 0, 0, /* ADDH2 */ +ODC(3), RH, RH, WO, 0, 0, 0, /* ADDH3 */ +ODC(2), RH, MO, 0, 0, 0, 0, /* SUBH2 */ +ODC(3), RH, RH, WO, 0, 0, 0, /* SUBH3 */ +ODC(2), RH, MO, 0, 0, 0, 0, /* MULH2 */ +ODC(3), RH, RH, WO, 0, 0, 0, /* MULH3 */ +ODC(2), RH, MO, 0, 0, 0, 0, /* DIVH2 */ +ODC(3), RH, RH, WO, 0, 0, 0, /* DIVH3 */ +ODC(2), RH, WB, 0, 0, 0, 0, /* CVTHB */ +ODC(2), RH, WW, 0, 0, 0, 0, /* CVTHW */ +ODC(2), RH, WL, 0, 0, 0, 0, /* CVTHL */ +ODC(2), RH, WL, 0, 0, 0, 0, /* CVTRHL */ +ODC(2), RB, WO, 0, 0, 0, 0, /* CVTBH */ +ODC(2), RW, WO, 0, 0, 0, 0, /* CVTWH */ +ODC(2), RL, WO, 0, 0, 0, 0, /* CVTLH */ +ODC(4), RH, RH, MO, BW, 0, 0, /* ACBH */ +ODC(2), RH, RO, 0, 0, 0, 0, /* MOVH */ +ODC(2), RH, RH, 0, 0, 0, 0, /* CMPH */ +ODC(2), RH, WO, 0, 0, 0, 0, /* MNEGH */ +ODC(1), RH, 0, 0, 0, 0, 0, /* TSTH */ +ODC(5), RH, RW, RH, WL, WO, 0, /* EMODH */ +ODC(3), RH, RW, AB, 0, 0, 0, /* POLYH */ +ODC(2), RH, 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 */ +ODC(1), WO, 0, 0, 0, 0, 0, /* CLRO */ +ODC(2), RO, RO, 0, 0, 0, 0, /* MOVO */ +ODC(2), AO, WL, 0, 0, 0, 0, /* MOVAO*/ +ODC(1), AO, 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, +ODC(2), RF, WO, 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, +ODC(2), RH, WL, 0, 0, 0, 0, /* CVTHF */ +ODC(2), RH, 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[] = { @@ -697,11 +701,11 @@ const char *opcode[] = { "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, /* 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, /* 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, @@ -713,91 +717,99 @@ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, "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, /* 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, /* 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, /* 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, /* 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 }; +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 }; +NULL +}; const int32 altop[] = { 0xD4, 0x7C, 0x7C, 0x17C, 0xDE, 0x7E, 0x7E, 0x17E, - 0xDF, 0x7F, 0x7F, 0x17F, 0x12, 0x13, 0x1E, 0x1F }; + 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)) + "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 + *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 + 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) + 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 */ -if ((sw & SIM_SW_STOP) && (PSL & PSL_CM)) /* stop in CM? */ - sw = sw | SWMASK ('P'); /* force CM print */ -dptr = find_dev_from_unit (uptr); /* find dev */ +if (uptr == NULL) uptr = &cpu_unit; /* anon = CPU */ +if ((sw & SIM_SW_STOP) && (PSL & PSL_CM)) /* stop in CM? */ + sw = sw | SWMASK ('P'); /* force CM print */ +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 */ +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 */ +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; -if ((sw & SWMASK ('A')) || (sw & SWMASK ('C'))) { /* char format? */ - for (vp = lnt - 1; vp >= 0; vp--) { - c = (int32) val[vp] & 0x7F; - fprintf (of, (c < 0x20)? "<%02X>": "%c", c); } - return -(lnt - 1); } /* return # chars */ +if ((sw & SWMASK ('A')) || (sw & SWMASK ('C'))) { /* char format? */ + for (vp = lnt - 1; vp >= 0; vp--) { + c = (int32) val[vp] & 0x7F; + fprintf (of, (c < 0x20)? "<%02X>": "%c", c); + } + return -(lnt - 1); /* return # chars */ + } -if ((sw & (SWMASK ('P') | SWMASK ('R'))) && /* cmode or rad50? */ - (uptr == &cpu_unit)) { - r = fprint_sym_cm (of, addr, val, sw); /* decode inst */ - if (r <= 0) return r; } +if ((sw & (SWMASK ('P') | SWMASK ('R'))) && /* cmode or rad50? */ + (uptr == &cpu_unit)) { + r = fprint_sym_cm (of, addr, val, sw); /* decode inst */ + if (r <= 0) return r; + } -if ((sw & SWMASK ('M')) && (uptr == &cpu_unit)) { /* inst format? */ - r = fprint_sym_m (of, addr, val); /* decode inst */ - if (r <= 0) return r; } +if ((sw & SWMASK ('M')) && (uptr == &cpu_unit)) { /* inst format? */ + r = fprint_sym_m (of, addr, val); /* decode inst */ + if (r <= 0) return r; + } -vp = 0; /* init ptr */ -GETNUM (num, lnt); /* get number */ +vp = 0; /* init ptr */ +GETNUM (num, lnt); /* get number */ fprint_val (of, (uint32) num, rdx, lnt * 8, PV_RZRO); return -(vp - 1); } @@ -805,12 +817,12 @@ return -(vp - 1); /* Symbolic decode for -m Inputs: - of = output stream - addr = current PC - *val = values to decode + of = output stream + addr = current PC + *val = values to decode Outputs: - return = if >= 0, error code - if < 0, number of extra bytes retired + return = if >= 0, error code + if < 0, number of extra bytes retired */ t_stat fprint_sym_m (FILE *of, uint32 addr, t_value *val) @@ -818,101 +830,117 @@ 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 = DR_GETNSP (drom[inst][0]); /* get # spec */ -if (numspec == 0) DR_GETUSP (drom[inst][0]); -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 (DR_LNT (disp) == L_OCTA) - 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 */ +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 = DR_GETNSP (drom[inst][0]); /* get # spec */ +if (numspec == 0) numspec = DR_GETUSP (drom[inst][0]); +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 (DR_LNT (disp) == L_OCTA) + 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 + *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 + vp = updated index into val */ int32 fprint_sym_qoimm (FILE *of, t_value *val, int32 vp, int32 lnt) @@ -921,26 +949,28 @@ 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; } } + 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 + +#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 + *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 + 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) @@ -951,49 +981,51 @@ 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 (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 */ +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 */ +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; -if ((sw & SWMASK ('A')) || ((*cptr == '\'') && cptr++)) /* ASCII char? */ - return parse_char (cptr, val, lnt); -if ((sw & SWMASK ('C')) || ((*cptr == '"') && cptr++)) /* ASCII string? */ - return parse_char (cptr, val, sim_emax); +if ((sw & SWMASK ('A')) || ((*cptr == '\'') && cptr++)) /* ASCII char? */ + return parse_char (cptr, val, lnt); +if ((sw & SWMASK ('C')) || ((*cptr == '"') && cptr++)) /* ASCII string? */ + return parse_char (cptr, val, sim_emax); -if ((sw & (SWMASK ('P') | SWMASK ('R'))) && /* cmode or rad50? */ - (uptr == &cpu_unit)) { - r = parse_sym_cm (cptr, addr, val, sw); /* try to parse */ - if (r <= 0) return r; } +if ((sw & (SWMASK ('P') | SWMASK ('R'))) && /* cmode or rad50? */ + (uptr == &cpu_unit)) { + r = parse_sym_cm (cptr, addr, val, sw); /* try to parse */ + if (r <= 0) return r; + } -if (uptr == &cpu_unit) { /* cpu only */ - r = parse_sym_m (cptr, addr, val); /* try to parse inst */ - if (r <= 0) return r; } +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 */ +num = (int32) get_uint (cptr, rdx, maxv[lnt], &r); /* get number */ if (r != SCPE_OK) return r; vp = 0; -PUTNUM (num, lnt); /* store */ +PUTNUM (num, lnt); /* store */ return -(lnt - 1); } /* Character input for -a or -c Inputs: - *cptr = pointer to input string - addr = current PC - *val = pointer to output values + *cptr = pointer to input string + addr = current PC + *val = pointer to output values Outputs: - status = > 0 error code - <= 0 -number of extra words + status = > 0 error code + <= 0 -number of extra words */ t_stat parse_char (char *cptr, t_value *val, int32 lnt) @@ -1002,20 +1034,21 @@ int32 vp; if (*cptr == 0) return SCPE_ARG; vp = 0; -while ((vp < lnt) && *cptr) { /* get chars */ - val[vp++] = *cptr++; } -return -(vp - 1); /* return # chars */ +while ((vp < lnt) && *cptr) { /* get chars */ + val[vp++] = *cptr++; + } +return -(vp - 1); /* return # chars */ } /* Symbolic input for -m Inputs: - *cptr = pointer to input string - addr = current PC - *val = pointer to output values + *cptr = pointer to input string + addr = current PC + *val = pointer to output values Outputs: - status = > 0 error code - <= 0 -number of extra words + status = > 0 error code + <= 0 -number of extra words */ t_stat parse_sym_m (char *cptr, uint32 addr, t_value *val) @@ -1024,26 +1057,30 @@ int32 i, numspec, disp, opc, vp; t_stat r; char gbuf[CBUFSIZE]; -cptr = get_glyph (cptr, gbuf, 0); /* get opcode */ +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? */ + 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 = DR_GETNSP (drom[opc][0]); /* get # specifiers */ +if (opc >= 0x100) val[vp++] = 0xFD; /* 2 byte? */ +val[vp++] = opc & 0xFF; /* store opcode */ +numspec = DR_GETNSP (drom[opc][0]); /* get # specifiers */ if (numspec == 0) numspec = DR_GETUSP (drom[opc][0]); -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; } +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); } @@ -1051,60 +1088,62 @@ 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 + 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 + vp = updated output pointer */ int32 parse_brdisp (char *cptr, uint32 addr, t_value *val, int32 vp, - int32 lnt, t_stat *r) + 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 */ +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))) - *r = SCPE_ARG; -else { PUTNUM (num, lnt + 1); /* store offset */ - *r = SCPE_OK; } + *r = SCPE_ARG; +else { + PUTNUM (num, lnt + 1); /* store offset */ + *r = SCPE_OK; + } 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 + 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 + 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))) +#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) { @@ -1115,194 +1154,228 @@ 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 & 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 04: - 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)? 0x10: 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)? 0x10: 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)? 0x10: 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)? 0x10: 0); - SPUTNUM (lit[0], 4); - 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 */ +*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; + } /* fall thru */ + 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 & 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 04: + vp = parse_sym_qoimm (lit, val, vp, 4, fl & SP_MINUS); + break; + } /* end case lnt */ + 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)? 0x10: 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)? 0x10: 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)? 0x10: 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)? 0x10: 0); + SPUTNUM (lit[0], 4); + 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; } @@ -1312,13 +1385,15 @@ 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 # */ +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; @@ -1329,8 +1404,9 @@ 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); } + if (minus) prev = lit[i] = ~lit[i] + (prev == 0); + PUTNUM (lit[i], 4); + } return vp; } diff --git a/VAX/vax_syscm.c b/VAX/vax_syscm.c index 6758acdd..34c0cc95 100644 --- a/VAX/vax_syscm.c +++ b/VAX/vax_syscm.c @@ -1,6 +1,6 @@ /* vax_syscm.c: PDP-11 compatibility mode symbolic decode and parse - Copyright (c) 1993-2004, Robert M Supnik + Copyright (c) 1993-2005, 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"), @@ -19,11 +19,11 @@ 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 + 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-Sep-04 RMS Cloned from pdp11_sys.c + 15-Sep-04 RMS Cloned from pdp11_sys.c */ #include "vax_defs.h" @@ -34,37 +34,38 @@ extern UNIT cpu_unit; /* Symbol tables */ /* 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_RSOP 4 /* reg, operand */ -#define I_V_BR 5 /* cond branch */ -#define I_V_6B 6 /* 6b literal */ -#define I_V_SOB 7 /* reg, disp */ -#define I_V_8B 8 /* 8b literal */ -#define I_V_DOP 9 /* double operand */ -#define I_V_CCC 10 /* CC clear */ -#define I_V_CCS 11 /* CC set */ -#define I_NPN (I_V_NPN << I_V_CL) -#define I_REG (I_V_REG << I_V_CL) -#define I_SOP (I_V_SOP << I_V_CL) -#define I_3B (I_V_3B << 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_RSOP (I_V_RSOP << I_V_CL) -#define I_SOB (I_V_SOB << 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) +#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_RSOP 4 /* reg, operand */ +#define I_V_BR 5 /* cond branch */ +#define I_V_6B 6 /* 6b literal */ +#define I_V_SOB 7 /* reg, disp */ +#define I_V_8B 8 /* 8b literal */ +#define I_V_DOP 9 /* double operand */ +#define I_V_CCC 10 /* CC clear */ +#define I_V_CCS 11 /* CC set */ +#define I_NPN (I_V_NPN << I_V_CL) +#define I_REG (I_V_REG << I_V_CL) +#define I_SOP (I_V_SOP << I_V_CL) +#define I_3B (I_V_3B << 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_RSOP (I_V_RSOP << I_V_CL) +#define I_SOB (I_V_SOB << 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, -0177000, 0177400, 0177700, 0177000, -0177400, 0170000, 0177777, 0177777 }; + 0177777, 0177770, 0177700, 0177770, + 0177000, 0177400, 0177700, 0177000, + 0177400, 0170000, 0177777, 0177777 + }; static const char *opcode[] = { "HALT","WAIT","RTI","BPT", @@ -110,7 +111,7 @@ static const char *opcode[] = { "SOB", "BPL","BMI","BHI","BLOS", "BVC","BVS","BCC","BCS", -"BHIS","BLO", /* encode only */ +"BHIS","BLO", /* encode only */ "EMT","TRAP", "CLRB","COMB","INCB","DECB", "NEGB","ADCB","SBCB","TSTB", @@ -118,7 +119,8 @@ static const char *opcode[] = { "MTPS","MFPD","MTPD","MFPS", "MOVB","CMPB","BITB","BICB", "BISB","SUB", -NULL }; +NULL +}; static const int32 opc_val[] = { 0000000+I_NPN, 0000001+I_NPN, 0000002+I_NPN, 0000003+I_NPN, @@ -172,24 +174,26 @@ static const int32 opc_val[] = { 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, --1 }; +-1 +}; -static const char *rname [] = -{ "R0", "R1", "R2", "R3", "R4", "R5", "SP", "PC" }; +static const char *rname [] = { + "R0", "R1", "R2", "R3", "R4", "R5", "SP", "PC" + }; 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 + *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 + count = -number of extra words retired */ int32 fprint_spec (FILE *of, t_addr addr, int32 spec, int32 nval) @@ -201,48 +205,58 @@ static const int32 pcwd[8] = { 0, 0, -1, -1, 0, 0, -1, -1 }; reg = spec & 07; mode = ((spec >> 3) & 07); switch (mode) { -case 0: - fprintf (of, "%s", rname[reg]); - break; -case 1: - fprintf (of, "(%s)", rname[reg]); - break; -case 2: - if (reg != 7) fprintf (of, "(%s)+", rname[reg]); - else fprintf (of, "#%-X", nval); - break; -case 3: - if (reg != 7) fprintf (of, "@(%s)+", rname[reg]); - else fprintf (of, "@#%-X", nval); - break; -case 4: - fprintf (of, "-(%s)", rname[reg]); - break; -case 5: - fprintf (of, "@-(%s)", rname[reg]); - break; -case 6: - if (reg != 7) fprintf (of, "%-X(%s)", nval, rname[reg]); - else fprintf (of, "%-X", (nval + addr + 4) & 0177777); - break; -case 7: - if (reg != 7) fprintf (of, "@%-X(%s)", nval, rname[reg]); - else fprintf (of, "@%-X", (nval + addr + 4) & 0177777); - break; } /* end case */ + + case 0: + fprintf (of, "%s", rname[reg]); + break; + + case 1: + fprintf (of, "(%s)", rname[reg]); + break; + + case 2: + if (reg != 7) fprintf (of, "(%s)+", rname[reg]); + else fprintf (of, "#%-X", nval); + break; + + case 3: + if (reg != 7) fprintf (of, "@(%s)+", rname[reg]); + else fprintf (of, "@#%-X", nval); + break; + + case 4: + fprintf (of, "-(%s)", rname[reg]); + break; + + case 5: + fprintf (of, "@-(%s)", rname[reg]); + break; + + case 6: + if (reg != 7) fprintf (of, "%-X(%s)", nval, rname[reg]); + else fprintf (of, "%-X", (nval + addr + 4) & 0177777); + break; + + case 7: + if (reg != 7) fprintf (of, "@%-X(%s)", nval, rname[reg]); + else fprintf (of, "@%-X", (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 + *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 + return = if >= 0, error code + if < 0, number of extra words retired */ t_stat fprint_sym_cm (FILE *of, t_addr addr, t_value *bytes, int32 sw) @@ -250,99 +264,107 @@ t_stat fprint_sym_cm (FILE *of, t_addr addr, t_value *bytes, int32 sw) int32 i, j, c1, c2, c3, inst, srcm, srcr, dstm, dstr; int32 l8b, brdisp, wd1; uint32 val[3]; -extern int32 FPS; for (i = j = 0; i < 3; i++, j = j + 2) - val[i] = (int32) (bytes[j] | (bytes[j + 1] << 8)); - -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 -1; } + val[i] = (int32) (bytes[j] | (bytes[j + 1] << 8)); + +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 -1; + } if (!(sw & SWMASK ('P')) || (addr & 1) || (addr > WMASK)) - return SCPE_ARG; + return SCPE_ARG; -inst = val[0]; /* inst */ +inst = val[0]; /* inst */ wd1 = 0; -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] & 0177777) == (inst & masks[j])) { /* match? */ - srcm = (inst >> 6) & 077; /* opr fields */ - srcr = srcm & 07; - dstm = inst & 077; - dstr = dstm & 07; - l8b = inst & 0377; - -/* Instruction decode */ +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] & 0177777) == (inst & masks[j])) { /* match? */ + srcm = (inst >> 6) & 077; /* opr fields */ + srcr = srcm & 07; + dstm = inst & 077; + dstr = dstm & 07; + l8b = inst & 0377; + switch (j) { /* case on class */ - switch (j) { /* case on class */ - case I_V_NPN: case I_V_CCC: case I_V_CCS: /* no operands */ - fprintf (of, "%s", opcode[i]); - break; - case I_V_REG: /* reg */ - fprintf (of, "%s %-s", opcode[i], rname[dstr]); - break; - case I_V_SOP: /* sop */ - fprintf (of, "%s ", opcode[i]); - wd1 = fprint_spec (of, addr, dstm, val[1]); - break; - case I_V_3B: /* 3b */ - fprintf (of, "%s %-X", opcode[i], dstr); - break; - case I_V_6B: /* 6b */ - fprintf (of, "%s %-X", opcode[i], dstm); - break; - case I_V_BR: /* cond branch */ - fprintf (of, "%s ", opcode[i]); - brdisp = (l8b + l8b + ((l8b & 0200)? 0177002: 2)) & 0177777; - fprintf (of, "%-X", (addr + brdisp) & 0177777); - break; - case I_V_8B: /* 8b */ - fprintf (of, "%s %-X", opcode[i], l8b); - break; - case I_V_SOB: /* sob */ - fprintf (of, "%s %s,", opcode[i], rname[srcr]); - brdisp = (dstm * 2) - 2; - fprintf (of, "%-X", (addr - brdisp) & 0177777); - break; - case I_V_RSOP: /* rsop */ - fprintf (of, "%s %s,", opcode[i], rname[srcr]); - wd1 = fprint_spec (of, addr, dstm, val[1]); - break; - case I_V_DOP: /* dop */ - fprintf (of, "%s ", opcode[i]); - wd1 = fprint_spec (of, addr, srcm, val[1]); - fprintf (of, ","); - wd1 += fprint_spec (of, addr - wd1 - wd1, dstm, - val[1 - wd1]); - break; - } /* end case */ - return ((wd1 * 2) - 1); - } /* end if */ - } /* end for */ -return SCPE_ARG; /* no match */ + case I_V_NPN: case I_V_CCC: case I_V_CCS: /* no operands */ + fprintf (of, "%s", opcode[i]); + break; + + case I_V_REG: /* reg */ + fprintf (of, "%s %-s", opcode[i], rname[dstr]); + break; + + case I_V_SOP: /* sop */ + fprintf (of, "%s ", opcode[i]); + wd1 = fprint_spec (of, addr, dstm, val[1]); + break; + + case I_V_3B: /* 3b */ + fprintf (of, "%s %-X", opcode[i], dstr); + break; + + case I_V_6B: /* 6b */ + fprintf (of, "%s %-X", opcode[i], dstm); + break; + + case I_V_BR: /* cond branch */ + fprintf (of, "%s ", opcode[i]); + brdisp = (l8b + l8b + ((l8b & 0200)? 0177002: 2)) & 0177777; + fprintf (of, "%-X", (addr + brdisp) & 0177777); + break; + + case I_V_8B: /* 8b */ + fprintf (of, "%s %-X", opcode[i], l8b); + break; + + case I_V_SOB: /* sob */ + fprintf (of, "%s %s,", opcode[i], rname[srcr]); + brdisp = (dstm * 2) - 2; + fprintf (of, "%-X", (addr - brdisp) & 0177777); + break; + + case I_V_RSOP: /* rsop */ + fprintf (of, "%s %s,", opcode[i], rname[srcr]); + wd1 = fprint_spec (of, addr, dstm, val[1]); + break; + + case I_V_DOP: /* dop */ + fprintf (of, "%s ", opcode[i]); + wd1 = fprint_spec (of, addr, srcm, val[1]); + fprintf (of, ","); + wd1 += fprint_spec (of, addr - wd1 - wd1, dstm, + val[1 - wd1]); + break; + } /* end case */ + + return ((wd1 * 2) - 1); + } /* 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 */ + +#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 - mchar = character to match after register name + *cptr = pointer to input string + mchar = character to match after register name Outputs: - rnum = 0..7 if a legitimate register - < 0 if error + rnum = 0..7 if a legitimate register + < 0 if error */ int32 get_reg (char *cptr, char mchar) @@ -351,19 +373,20 @@ int32 i; if (*(cptr + 2) != mchar) return -1; for (i = 0; i < 8; i++) { - if (strncmp (cptr, rname[i], 2) == 0) return i; } + if (strncmp (cptr, rname[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 + *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 + cptr = pointer to next character in input string + NULL if parsing error Flags: 0 (no result), A_NUM (number), A_REL (relative) */ @@ -375,124 +398,143 @@ 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++; } +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, 16); -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? */ +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 + *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 Outputs: - status = = -1 extra word decoded - = 0 ok - = +1 error + status = = -1 extra word decoded + = 0 ok + = +1 error */ t_stat get_spec (char *cptr, t_addr addr, int32 n1, int32 *sptr, int32 *dptr) { int32 reg, indir, pflag, disp; -indir = 0; /* no indirect */ +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++; } +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, ')')) < 0) return 1; - cptr = cptr + 4; - if (*cptr == '+') { /* autoincrement? */ - pflag = pflag | A_PLS; - cptr++; } } +if (*cptr == '(') { /* register index? */ + pflag = pflag | A_PAR; + if ((reg = get_reg (cptr + 1, ')')) < 0) return 1; + cptr = cptr + 4; + if (*cptr == '+') { /* autoincrement? */ + pflag = pflag | A_PLS; + cptr++; + } + } else if ((reg = get_reg (cptr, 0)) >= 0) { - pflag = pflag | A_REG; - cptr = cptr + 2; } -if (*cptr != 0) return 1; /* all done? */ - -/* Specifier decode, continued */ + pflag = pflag | A_REG; + cptr = cptr + 2; + } +if (*cptr != 0) return 1; /* all done? */ -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 */ - 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 */ - *sptr = 067 + indir; - *dptr = (disp - addr - 4 + (2 * n1)) & 0177777; - return -1; -default: - return 1; } /* end case */ +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 */ + 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 */ + *sptr = 067 + indir; + *dptr = (disp - addr - 4 + (2 * n1)) & 0177777; + 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 + *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 + status = > 0 error code + <= 0 -number of extra words */ t_stat parse_sym_cm (char *cptr, t_addr addr, t_value *bytes, int32 sw) @@ -502,86 +544,99 @@ int32 val[3]; t_stat r; char *tptr, gbuf[CBUFSIZE]; -if (sw & SWMASK ('R')) return SCPE_ARG; /* radix 50 */ +if (sw & SWMASK ('R')) return SCPE_ARG; /* radix 50 */ if (!(sw & SWMASK ('P')) || (addr & 1) || (addr > WMASK)) - return SCPE_ARG; + return SCPE_ARG; -cptr = get_glyph (cptr, gbuf, 0); /* get opcode */ +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 */ +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, 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 = (int32) get_uint (gbuf, 16, (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) - disp = (disp - addr) & 0177777; - 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, 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) - disp = (disp - addr) & 0177777; - 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, 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])) > 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])) > 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])) > 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? */ +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, 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 = (int32) get_uint (gbuf, 16, (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) + disp = (disp - addr) & 0177777; + 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, 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) + disp = (disp - addr) & 0177777; + 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, 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])) > 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])) > 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])) > 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? */ for (i = j = 0; i < 3; i++, j = j + 2) { - bytes[j] = val[i] & BMASK; - bytes[j + 1] = (val[i] >> 8) & BMASK; } + bytes[j] = val[i] & BMASK; + bytes[j + 1] = (val[i] >> 8) & BMASK; + } return ((2 * (n1 + n2)) - 1); } diff --git a/VAX/vax_sysdev.c b/VAX/vax_sysdev.c index 64b8994d..b7e3f248 100644 --- a/VAX/vax_sysdev.c +++ b/VAX/vax_sysdev.c @@ -19,153 +19,154 @@ 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 + 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 chip and VAX 3900 system-specific registers and devices. - rom bootstrap ROM (no registers) - nvr non-volatile ROM (no registers) - csi console storage input - cso console storage output - sysd system devices (SSC miscellany) + rom bootstrap ROM (no registers) + nvr non-volatile ROM (no registers) + csi console storage input + cso console storage output + sysd system devices (SSC miscellany) - 10-Mar-05 RMS Fixed bug in timer schedule routine (from Mark Hittinger) - 30-Sep-04 RMS Moved CADR, MSER, CONPC, CONPSL, machine_check, cpu_boot, - con_halt here from vax_cpu.c - Moved model-specific IPR's here from vax_cpu1.c - 09-Sep-04 RMS Integrated powerup into RESET (with -p) - Added model-specific registers and routines from CPU - 23-Jan-04 MP Added extended physical memory support (Mark Pizzolato) - 07-Jun-03 MP Added calibrated delay to ROM reads (Mark Pizzolato) - Fixed calibration problems interval timer (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) + 16-Aug-05 RMS Fixed C++ declaration and cast problems + 10-Mar-05 RMS Fixed bug in timer schedule routine (from Mark Hittinger) + 30-Sep-04 RMS Moved CADR, MSER, CONPC, CONPSL, machine_check, cpu_boot, + con_halt here from vax_cpu.c + Moved model-specific IPR's here from vax_cpu1.c + 09-Sep-04 RMS Integrated powerup into RESET (with -p) + Added model-specific registers and routines from CPU + 23-Jan-04 MP Added extended physical memory support (Mark Pizzolato) + 07-Jun-03 MP Added calibrated delay to ROM reads (Mark Pizzolato) + Fixed calibration problems interval timer (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) +#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) +#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 */ +#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) +#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) +#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 */ +#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) +#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 */ +#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 +#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 +#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 */ +#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) +#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 */ +#define TMR_INC 10000 /* usec/interval */ /* SSC timer vector */ -#define TMR_VEC_MASK 0x000003FC /* vector */ +#define TMR_VEC_MASK 0x000003FC /* vector */ /* SSC address strobes */ -#define SSCADS_MASK 0x3FFFFFFC /* match or mask */ +#define SSCADS_MASK 0x3FFFFFFC /* match or mask */ extern int32 R[16]; extern int32 STK[5]; @@ -188,29 +189,29 @@ extern int32 MSER; extern int32 tmr_poll; extern int32 cpu_extmem; -uint32 *rom = NULL; /* boot ROM */ -uint32 *nvr = NULL; /* non-volatile mem */ -int32 CADR = 0; /* cache disable reg */ -int32 MSER = 0; /* mem sys error reg */ -int32 conpc, conpsl; /* console reg */ -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 */ +uint32 *rom = NULL; /* boot ROM */ +uint32 *nvr = NULL; /* non-volatile mem */ +int32 CADR = 0; /* cache disable reg */ +int32 MSER = 0; /* mem sys error reg */ +int32 conpc, conpsl; /* console reg */ +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 */ +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); @@ -275,56 +276,61 @@ 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 + 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 } }; + { NULL } + }; MTAB rom_mod[] = { - { UNIT_NODELAY, UNIT_NODELAY, "fast access", "NODELAY", NULL }, - { UNIT_NODELAY, 0, "1usec calibrated access", "DELAY", NULL }, - { 0 } }; + { 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 }; + "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 + nvr_dev NVR device descriptor + nvr_unit NVR units + nvr_reg NVR register list */ UNIT nvr_unit = - { UDATA (NULL, UNIT_FIX+UNIT_BINK, NVRSIZE) }; + { UDATA (NULL, UNIT_FIX+UNIT_BINK, NVRSIZE) }; REG nvr_reg[] = { - { NULL } }; + { 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 }; - + "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 + 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 } }; @@ -332,31 +338,34 @@ 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 } }; + { 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 } }; + { 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 }; + "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 + 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 } }; @@ -364,78 +373,86 @@ 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 } }; + { 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 } }; + { 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 }; - + "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 + 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 } }; +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) } }; + { UDATA (&tmr_svc, 0, 0) }, + { UDATA (&tmr_svc, 0, 0) } + }; REG sysd_reg[] = { - { HRDATA (CADR, CADR, 8) }, - { HRDATA (MSER, MSER, 8) }, - { HRDATA (CONPC, conpc, 32) }, - { HRDATA (CONPSL, conpsl, 32) }, - { 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 } }; + { HRDATA (CADR, CADR, 8) }, + { HRDATA (MSER, MSER, 8) }, + { HRDATA (CONPC, conpc, 32) }, + { HRDATA (CONPSL, conpsl, 32) }, + { 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 }; - + "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 @@ -456,7 +473,7 @@ DEVICE sysd_dev = { int32 rom_swapb(int32 val) { return ((val << 24) & 0xff000000) | (( val << 8) & 0xff0000) | - ((val >> 8) & 0xff00) | ((val >> 24) & 0xff); + ((val >> 8) & 0xff00) | ((val >> 24) & 0xff); } int32 rom_read_delay (int32 val) @@ -470,11 +487,11 @@ if (rom_unit.flags & UNIT_NODELAY) return val; 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 */ + 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, @@ -482,18 +499,20 @@ if (rom_delay == 0) { 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 < 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)); + loopval |= (loopval + val) ^ rom_swapb (rom_swapb (loopval + val)); return val + loopval; } @@ -541,11 +560,11 @@ return SCPE_OK; t_stat rom_reset (DEVICE *dptr) { -if (rom == NULL) rom = calloc (ROMSIZE >> 2, sizeof (int32)); +if (rom == NULL) rom = (uint32 *) calloc (ROMSIZE >> 2, sizeof (uint32)); if (rom == NULL) return SCPE_MEM; return SCPE_OK; } - + /* NVR: non-volatile RAM - stored in a buffered file */ int32 nvr_rd (int32 pa) @@ -559,10 +578,11 @@ 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)); } +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; } @@ -596,9 +616,10 @@ return SCPE_OK; 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; } + nvr = (uint32 *) calloc (NVRSIZE >> 2, sizeof (uint32)); + nvr_unit.filebuf = nvr; + ssc_cnf = ssc_cnf | SSCCNF_BLO; + } if (nvr == NULL) return SCPE_MEM; return SCPE_OK; } @@ -612,9 +633,11 @@ 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 = (uint32) uptr->capac; - ssc_cnf = ssc_cnf & ~SSCCNF_BLO; } + uptr->flags = uptr->flags & ~(UNIT_ATTABLE | UNIT_BUFABLE); +else { + uptr->hwmark = (uint32) uptr->capac; + ssc_cnf = ssc_cnf & ~SSCCNF_BLO; + } return r; } @@ -626,10 +649,10 @@ t_stat r; r = detach_unit (uptr); if ((uptr->flags & UNIT_ATT) == 0) - uptr->flags = uptr->flags & ~(UNIT_ATTABLE | UNIT_BUFABLE); + uptr->flags = uptr->flags & ~(UNIT_ATTABLE | UNIT_BUFABLE); return r; } - + /* CSI: console storage input */ int32 csrs_rd (void) @@ -648,7 +671,7 @@ 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); + SET_INT (CSI); csi_csr = (csi_csr & ~CSICSR_RW) | (data & CSICSR_RW); return; } @@ -660,7 +683,7 @@ csi_csr = 0; CLR_INT (CSI); return SCPE_OK; } - + /* CSO: console storage output */ int32 csts_rd (void) @@ -672,7 +695,7 @@ 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); + SET_INT (CSO); cso_csr = (cso_csr & ~CSOCSR_RW) | (data & CSOCSR_RW); return; } @@ -692,9 +715,10 @@ 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; } + perror ("CSO I/O error"); + clearerr (cso_unit.fileref); + return SCPE_IOERR; + } cso_unit.pos = cso_unit.pos + 1; return SCPE_OK; } @@ -704,10 +728,10 @@ t_stat cso_reset (DEVICE *dptr) cso_unit.buf = 0; cso_csr = CSR_DONE; CLR_INT (CSO); -sim_cancel (&cso_unit); /* deactivate unit */ +sim_cancel (&cso_unit); /* deactivate unit */ return SCPE_OK; } - + /* SYSD: SSC access mechanisms and devices - IPR space read/write routines @@ -729,108 +753,143 @@ 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; -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_SID: /* SID */ - val = CVAX_SID | CVAX_UREV; - break; -default: - ssc_bto = ssc_bto | SSCBTO_BTO; /* set BTO */ - val = 0; - break; } + + 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: /* TODR */ + val = todr_rd (); + 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_SID: /* SID */ + val = CVAX_SID | CVAX_UREV; + 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_CADR: /* CADR */ - CADR = (val & CADR_RW) | CADR_MBO; - break; -case MT_MSER: /* MSER */ - MSER = MSER & MSER_HM; - break; -case MT_IORESET: /* IORESET */ - ioreset_wr (val); - break; -case MT_SID: -case MT_CONPC: -case MT_CONPSL: /* halt reg */ - RSVD_OPND_FAULT; -default: - ssc_bto = ssc_bto | SSCBTO_BTO; /* set BTO */ - break; } + + 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_CADR: /* CADR */ + CADR = (val & CADR_RW) | CADR_MBO; + break; + + case MT_MSER: /* MSER */ + MSER = MSER & MSER_HM; + break; + + case MT_IORESET: /* IORESET */ + ioreset_wr (val); + break; + + case MT_SID: + case MT_CONPC: + case MT_CONPSL: /* halt reg */ + RSVD_OPND_FAULT; + + 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 @@ -838,32 +897,34 @@ return; 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 { /* 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 } }; + { 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 + pa = physical address + lnt = length (BWLQ) - ignored Output: - longword of data + longword of data */ int32 ReadReg (int32 pa, int32 lnt) @@ -871,8 +932,9 @@ 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); } + 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; @@ -881,11 +943,11 @@ return 0; /* WriteReg - write register space Inputs: - pa = physical address - val = data to write, right justified in 32b longword - lnt = length (BWLQ) + pa = physical address + val = data to write, right justified in 32b longword + lnt = length (BWLQ) Outputs: - none + none */ void WriteReg (int32 pa, int32 val, int32 lnt) @@ -893,14 +955,16 @@ 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; } } + 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 @@ -919,15 +983,21 @@ 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; -case 18: /* KA655X ext mem */ - if (cpu_extmem) return ((int32) MEMSIZE); - MACH_CHECK (MCHK_READ); } + + 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; + + case 18: /* KA655X ext mem */ + if (cpu_extmem) return ((int32) MEMSIZE); + MACH_CHECK (MCHK_READ); + } + return 0; } @@ -935,42 +1005,54 @@ 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 */ +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? */ - int32 rg_g = rg & ~3; /* group of 4 */ - for (i = rg_g; i < (rg_g + 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; -case 18: - MACH_CHECK (MCHK_WRITE); } + + default: /* config reg */ + if (val & CMCNF_SRQ) { /* sig request? */ + int32 rg_g = rg & ~3; /* group of 4 */ + for (i = rg_g; i < (rg_g + 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; + + case 18: + MACH_CHECK (MCHK_WRITE); + } + 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; } +switch (rg) { + + case 0: /* CACR */ + return ka_cacr; + + case 1: /* BDR */ + return ka_bdr; + } + return 0; } @@ -978,9 +1060,10 @@ 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); } +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; } @@ -988,7 +1071,7 @@ int32 sysd_hlt_enb (void) { return ka_bdr & BDR_BRKENB; } - + /* Cache diagnostic space */ int32 cdg_rd (int32 pa) @@ -996,12 +1079,12 @@ 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 & ~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); + (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; } @@ -1009,22 +1092,24 @@ 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 */ +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; } + if (val & 1) odd = odd ^ 1; + } return odd; } - + /* SSC registers - byte/word merges done in WriteReg */ int32 ssc_rd (int32 pa) @@ -1032,52 +1117,77 @@ 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]; } + + 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; } @@ -1085,81 +1195,105 @@ 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)); } +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; } + + 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 @@ -1171,7 +1305,7 @@ return; 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 + clock events at 100Hz using calibrated line clock delay and when the remaining time value gets small enough, behave like the small case above. @@ -1198,40 +1332,45 @@ 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; } +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 */ +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); } + if (tmr) CLR_INT (TMR1); + else CLR_INT (TMR0); + } return; } @@ -1239,9 +1378,9 @@ return; t_stat tmr_svc (UNIT *uptr) { -int32 tmr = uptr - sysd_dev.units; /* get timer # */ +int32 tmr = uptr - sysd_dev.units; /* get timer # */ -tmr_incr (tmr, tmr_inc[tmr]); /* incr timer */ +tmr_incr (tmr, tmr_inc[tmr]); /* incr timer */ return SCPE_OK; } @@ -1249,24 +1388,29 @@ return SCPE_OK; void tmr_incr (int32 tmr, uint32 inc) { -uint32 new_tir = tmr_tir[tmr] + inc; /* add incr */ +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 */ +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; } @@ -1277,12 +1421,15 @@ 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; } +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)) { @@ -1292,8 +1439,9 @@ if ((tmr_inc[tmr] == TMR_INC) && (tmr_time > clk_time)) { 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; } + tmr_inc[tmr] = (uint32) (((double) clk_time * TMR_INC) / tmr_poll); + tmr_time = clk_time; + } sim_activate (&sysd_unit[tmr], tmr_time); return; } @@ -1307,31 +1455,32 @@ int32 tmr1_inta (void) { return tmr_tivr[1]; } - + /* Machine check */ int32 machine_check (int32 p1, int32 opc, int32 cc, int32 delta) { int32 i, st1, st2, p2, hsir, acc; -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; } +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); + (hsir << 16) | + ((CADR & 0xFF) << 8) | + (MSER & 0xFF); st2 = 0x00C07000 + (delta & 0xFF); -cc = intexc (SCB_MCHK, cc, 0, IE_SVE); /* take exception */ -acc = ACC_MASK (KERN); /* in kernel mode */ +cc = intexc (SCB_MCHK, cc, 0, IE_SVE); /* take exception */ +acc = ACC_MASK (KERN); /* in kernel mode */ 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 */ +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; return cc; } @@ -1342,17 +1491,17 @@ 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 */ +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 */ } /* Bootstrap */ @@ -1368,12 +1517,13 @@ 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 ka655x.bin\n"); - if (sim_log) fprintf (sim_log, - "Loading boot code from ka655x.bin\n"); - r = load_cmd (0, "-R ka655x.bin"); - if (r != SCPE_OK) return r; } +if (*rom == 0) { /* no boot? */ + printf ("Loading boot code from ka655x.bin\n"); + if (sim_log) fprintf (sim_log, + "Loading boot code from ka655x.bin\n"); + r = load_cmd (0, "-R ka655x.bin"); + if (r != SCPE_OK) return r; + } return SCPE_OK; } @@ -1383,11 +1533,12 @@ t_stat sysd_reset (DEVICE *dptr) { int32 i; -if (sim_switches & SWMASK ('P')) sysd_powerup (); /* powerup? */ +if (sim_switches & SWMASK ('P')) sysd_powerup (); /* powerup? */ 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]); } + 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); @@ -1407,8 +1558,9 @@ 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; } + tmr_tivr[i] = 0; + ssc_adsm[i] = ssc_adsk[i] = 0; + } ka_cacr = 0; ssc_base = SSCBASE; ssc_cnf = ssc_cnf & SSCCNF_BLO; diff --git a/VAX/vax_syslist.c b/VAX/vax_syslist.c index d1c2a2c6..90d541d0 100644 --- a/VAX/vax_syslist.c +++ b/VAX/vax_syslist.c @@ -1,6 +1,6 @@ /* vax_sys.c: VAX simulator interface - Copyright (c) 1998-2004, Robert M Supnik + Copyright (c) 1998-2005, 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"), @@ -19,11 +19,11 @@ 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 + 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-Oct-2004 RMS Cloned from vax_sys.c + 01-Oct-2004 RMS Cloned from vax_sys.c */ #include "vax_defs.h" @@ -55,41 +55,42 @@ extern void rom_wr_B (int32 pa, int32 val); extern UNIT cpu_unit; 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, - &dz_dev, - &vh_dev, - &lpt_dev, - &rl_dev, - &rq_dev, - &rqb_dev, - &rqc_dev, - &rqd_dev, - &ry_dev, - &ts_dev, - &tq_dev, - &xq_dev, - &xqb_dev, - NULL }; - + &cpu_dev, + &tlb_dev, + &rom_dev, + &nvr_dev, + &sysd_dev, + &qba_dev, + &tti_dev, + &tto_dev, + &csi_dev, + &cso_dev, + &clk_dev, + &dz_dev, + &vh_dev, + &lpt_dev, + &rl_dev, + &rq_dev, + &rqb_dev, + &rqc_dev, + &rqd_dev, + &ry_dev, + &ts_dev, + &tq_dev, + &xq_dev, + &xqb_dev, + NULL + }; + /* 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 + -r load ROM + -n load NVR + -o for memory, specify origin */ t_stat sim_load (FILE *fileref, char *cptr, char *fnam, int flag) @@ -98,27 +99,33 @@ t_stat r; int32 i; uint32 origin, limit; extern int32 ssc_cnf; -#define SSCCNF_BLO 0x80000000 +#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_B (origin, i); /* not writeable */ - else WriteB (origin, i); /* store byte */ - origin = origin + 1; } +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_B (origin, i); /* not writeable */ + else WriteB (origin, i); /* store byte */ + origin = origin + 1; + } return SCPE_OK; } diff --git a/VAX/vaxmod_defs.h b/VAX/vaxmod_defs.h index c286c036..cb66464c 100644 --- a/VAX/vaxmod_defs.h +++ b/VAX/vaxmod_defs.h @@ -1,6 +1,6 @@ /* vaxmod_defs.h: VAX model-specific definitions file - Copyright (c) 1998-2004, Robert M Supnik + Copyright (c) 1998-2005, 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"), @@ -19,23 +19,24 @@ 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 + 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-Sep-04 RMS Removed map_address prototype - 16-Jun-04 RMS Added DHQ11 support - 21-Mar-04 RMS Added RXV21 support - 25-Jan-04 RMS Removed local debug logging support - RMS,MP Added "KA655X" support - 29-Dec-03 RMS Added Q18 definition for PDP11 compatibility - 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 + 15-Jun-05 RMS Added QDSS support + 12-Sep-04 RMS Removed map_address prototype + 16-Jun-04 RMS Added DHQ11 support + 21-Mar-04 RMS Added RXV21 support + 25-Jan-04 RMS Removed local debug logging support + RMS,MP Added "KA655X" support + 29-Dec-03 RMS Added Q18 definition for PDP11 compatibility + 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. The simulator defines an extended physical memory variant of the KA655, @@ -43,258 +44,258 @@ System memory map - 0000 0000 - 03FF FFFF main memory (KA655) - 0400 0000 - 0FFF FFFF reserved (KA655), main memory (KA655X) - 1000 0000 - 13FF FFFF cache diagnostic space (KA655), main memory (KA655X) - 1400 0000 - 1FFF FFFF reserved (KA655), main memory (KA655X) + 0000 0000 - 03FF FFFF main memory (KA655) + 0400 0000 - 0FFF FFFF reserved (KA655), main memory (KA655X) + 1000 0000 - 13FF FFFF cache diagnostic space (KA655), main memory (KA655X) + 1400 0000 - 1FFF FFFF reserved (KA655), main memory (KA655X) - 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 + 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 */ -#ifdef FULL_VAX /* subset VAX */ +#ifdef FULL_VAX /* subset VAX */ #undef FULL_VAX #endif #ifndef _VAXMOD_DEFS_H_ -#define _VAXMOD_DEFS_H_ 1 +#define _VAXMOD_DEFS_H_ 1 /* 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 */ +#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 */ /* Machine specific IPRs */ -#define MT_CADR 37 -#define MT_MSER 39 -#define MT_CONPC 42 -#define MT_CONPSL 43 -#define MT_IORESET 55 +#define MT_CADR 37 +#define MT_MSER 39 +#define MT_CONPC 42 +#define MT_CONPSL 43 +#define MT_IORESET 55 /* Memory system error register */ -#define MSER_HM 0x80 /* hit/miss */ -#define MSER_CPE 0x40 /* CDAL par err */ -#define MSER_CPM 0x20 /* CDAL mchk */ +#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 +#define CADR_RW 0xF3 +#define CADR_MBO 0x0C /* Memory */ -#define MAXMEMWIDTH 26 /* max mem, std KA655 */ -#define MAXMEMSIZE (1 << MAXMEMWIDTH) /* max mem size */ -#define MAXMEMWIDTH_X 29 /* max mem, KA655X */ -#define MAXMEMSIZE_X (1 << MAXMEMWIDTH_X) -#define INITMEMSIZE (1 << 24) /* initial memory size */ -#define MEMSIZE (cpu_unit.capac) -#define ADDR_IS_MEM(x) (((uint32) (x)) < MEMSIZE) +#define MAXMEMWIDTH 26 /* max mem, std KA655 */ +#define MAXMEMSIZE (1 << MAXMEMWIDTH) /* max mem size */ +#define MAXMEMWIDTH_X 29 /* max mem, KA655X */ +#define MAXMEMSIZE_X (1 << MAXMEMWIDTH_X) +#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))) +#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))) +#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))) +#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 */ +#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 */ +#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 */ +#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 CMCTLSIZE (19 << 2) /* KA655X extra reg */ -#define CMCTLBASE (REGBASE + 0x100) /* CMCTL addr base */ +/* #define CMCTLSIZE (18 << 2) /* 18 registers */ +#define CMCTLSIZE (19 << 2) /* KA655X extra reg */ +#define CMCTLBASE (REGBASE + 0x100) /* CMCTL addr base */ /* SSC registers */ -#define SSCSIZE 0x150 /* SSC size */ -#define SSCBASE 0x20140000 /* SSC base */ +#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))) +#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 */ +#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) +#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) +#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 */ +#define TMR_CLK 0 /* 100Hz clock */ /* I/O system definitions */ -#define DZ_MUXES 4 /* max # of DZV muxes */ -#define DZ_LINES 4 /* lines per DZV mux */ -#define VH_MUXES 4 /* max # of DHQ muxes */ -#define MT_MAXFR (1 << 16) /* magtape max rec */ -#define AUTO_LNT 34 /* autoconfig ranks */ +#define DZ_MUXES 4 /* max # of DZV muxes */ +#define DZ_LINES 4 /* lines per DZV mux */ +#define VH_MUXES 4 /* max # of DHQ muxes */ +#define MT_MAXFR (1 << 16) /* magtape max rec */ +#define AUTO_LNT 34 /* autoconfig ranks */ -#define DEV_V_UBUS (DEV_V_UF + 0) /* Unibus */ -#define DEV_V_QBUS (DEV_V_UF + 1) /* Qbus */ -#define DEV_V_Q18 (DEV_V_UF + 2) /* Qbus, mem <= 256KB */ -#define DEV_V_FLTA (DEV_V_UF + 3) /* flt addr */ -#define DEV_UBUS (1u << DEV_V_UBUS) -#define DEV_QBUS (1u << DEV_V_QBUS) -#define DEV_Q18 (1u << DEV_V_Q18) -#define DEV_FLTA (1u << DEV_V_FLTA) +#define DEV_V_UBUS (DEV_V_UF + 0) /* Unibus */ +#define DEV_V_QBUS (DEV_V_UF + 1) /* Qbus */ +#define DEV_V_Q18 (DEV_V_UF + 2) /* Qbus, mem <= 256KB */ +#define DEV_V_FLTA (DEV_V_UF + 3) /* flt addr */ +#define DEV_UBUS (1u << DEV_V_UBUS) +#define DEV_QBUS (1u << DEV_V_QBUS) +#define DEV_Q18 (1u << DEV_V_Q18) +#define DEV_FLTA (1u << DEV_V_FLTA) -#define UNIBUS FALSE /* 22b only */ +#define UNIBUS FALSE /* 22b only */ -#define DEV_RDX 16 /* default device radix */ +#define DEV_RDX 16 /* default device radix */ /* Device information block */ -#define VEC_DEVMAX 4 /* max device vec */ +#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; +typedef struct { + 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 */ + } 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_VH (IOPAGEBASE + 000440) /* DHQ11 */ -#define IOLN_VH 020 -#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_RX (IOPAGEBASE + 017170) /* RXV11 */ -#define IOLN_RX 004 -#define IOBA_RY (IOPAGEBASE + 017170) /* RXV21 */ -#define IOLN_RY 004 -#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 +#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_VH (IOPAGEBASE + 000440) /* DHQ11 */ +#define IOLN_VH 020 +#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_RX (IOPAGEBASE + 017170) /* RXV11 */ +#define IOLN_RX 004 +#define IOBA_RY (IOPAGEBASE + 017170) /* RXV21 */ +#define IOLN_RY 004 +#define IOBA_QDSS (IOPAGEBASE + 017400) /* QDSS */ +#define IOLN_QDSS 002 +#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 @@ -304,123 +305,118 @@ typedef struct pdp_dib DIB; /* IPL 16 */ -#define INT_V_CLK 0 /* clock */ +#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 */ -#define INT_V_RY 8 /* RXV21 */ +#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 */ +#define INT_V_RY 8 /* RXV21 */ /* 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_V_VHRX 9 /* DHQ11 */ -#define INT_V_VHTX 10 +#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_V_VHRX 9 /* DHQ11 */ +#define INT_V_VHTX 10 +#define INT_V_QDSS 11 /* QDSS */ -#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_RY (1u << INT_V_RY) -#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 INT_VHRX (1u << INT_V_VHRX) -#define INT_VHTX (1u << INT_V_VHTX) +#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_RY (1u << INT_V_RY) +#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 INT_VHRX (1u << INT_V_VHRX) +#define INT_VHTX (1u << INT_V_VHTX) +#define INT_QDSS (1u << INT_V_QDSS) -#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_RY (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_VHRX (0x14 - IPL_HMIN) -#define IPL_VHTX (0x14 - IPL_HMIN) +#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_RY (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_VHRX (0x14 - IPL_HMIN) +#define IPL_VHTX (0x14 - IPL_HMIN) +#define IPL_QDSS (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 */ +#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_RY (VEC_Q + 0264) -#define VEC_DZRX (VEC_Q + 0300) -#define VEC_DZTX (VEC_Q + 0304) -#define VEC_VHRX (VEC_Q + 0310) -#define VEC_VHTX (VEC_Q + 0314) - -/* Autoconfigure ranks */ - -#define RANK_DZ 8 -#define RANK_RL 14 -#define RANK_RX 18 -#define RANK_RQ 26 -#define RANK_TQ 30 -#define RANK_VH 32 +#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_RX (VEC_Q + 0264) +#define VEC_RY (VEC_Q + 0264) +#define VEC_DZRX (VEC_Q + 0300) +#define VEC_DZTX (VEC_Q + 0304) +#define VEC_VHRX (VEC_Q + 0310) +#define VEC_VHTX (VEC_Q + 0314) /* 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 */ +#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 0x1 /* intexc */ -#define LOG_CPU_R 0x2 /* REI */ -#define LOG_CPU_P 0x4 /* context */ +#define LOG_CPU_I 0x1 /* intexc */ +#define LOG_CPU_R 0x2 /* REI */ +#define LOG_CPU_P 0x4 /* context */ /* Function prototypes for I/O */ @@ -434,6 +430,6 @@ 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); +t_stat auto_config (char *name, int32 num); #endif diff --git a/descrip.mms b/descrip.mms index 32c9c91b..9da3aa7c 100644 --- a/descrip.mms +++ b/descrip.mms @@ -376,7 +376,7 @@ PDP11_SOURCE2 = $(PDP11_DIR)PDP11_TM.C,$(PDP11_DIR)PDP11_TS.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_VH.C,$(PDP11_DIR)PDP11_RH.C + $(PDP11_DIR)PDP11_VH.C,$(PDP11_DIR)PDP11_RH.C,\ $(PDP11_DIR)PDP11_XU.C,$(PDP11_DIR)PDP11_TU.C PDP11_OPTIONS = /INCLUDE=($(SIMH_DIR),$(PDP11_DIR)$(PCAP_INC))\ /DEFINE=($(CC_DEFS),"VM_PDP11=1"$(PCAP_DEFS)) diff --git a/scp.c b/scp.c index aa24ee86..4ed0a275 100644 --- a/scp.c +++ b/scp.c @@ -19,133 +19,137 @@ 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 + 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-May-05 RMS Revised syntax for SET DEBUG (from Dave Bryan) - 22-Mar-05 JDB Modified DO command to allow ten-level nesting - 18-Mar-05 RMS Moved DETACH tests into detach_unit (from Dave Bryan) - Revised interface to fprint_sym, fparse_sym - 07-Feb-05 RMS Added ASSERT command (from Dave Bryan) - 02-Feb-05 RMS Fixed bug in global register search - 26-Dec-04 RMS Qualified SAVE examine, RESTORE deposit with SIM_SW_REST - 10-Nov-04 JDB Fixed logging of errors from cmds in "do" file - 05-Nov-04 RMS Moved SET/SHOW DEBUG under CONSOLE hierarchy - Renamed unit OFFLINE/ONLINE to DISABLED/ENABLED (from Dave Bryan) - Revised to flush output files after simulation stop (from Dave Bryan) - 15-Oct-04 RMS Fixed HELP to suppress duplicate descriptions - 27-Sep-04 RMS Fixed comma-separation options in set (from David Bryan) - 09-Sep-04 RMS Added -p option for RESET - 13-Aug-04 RMS Qualified RESTORE detach with SIM_SW_REST - 17-Jul-04 RMS Added ECHO command (from Dave Bryan) - 12-Jul-04 RMS Fixed problem ATTACHing to read only files - (found by John Dundas) - 28-May-04 RMS Added SET/SHOW CONSOLE - 14-Feb-04 RMS Updated SAVE/RESTORE (V3.2) - RMS Added debug print routines (from Dave Hittner) - RMS Added sim_vm_parse_addr and sim_vm_fprint_addr - RMS Added REG_VMAD support - RMS Split out libraries - RMS Moved logging function to SCP - RMS Exposed step counter interface(s) - RMS Fixed double logging of SHOW BREAK (found by Mark Pizzolato) - RMS Fixed implementation of REG_VMIO - RMS Added SET/SHOW DEBUG, SET/SHOW DEBUG, - SHOW MODIFIERS, SHOW RADIX - RMS Changed sim_fsize to take uptr argument - 29-Dec-03 RMS Added Telnet console output stall support - 01-Nov-03 RMS Cleaned up implicit detach on attach/restore - Fixed bug in command line read while logging (found by Mark Pizzolato) - 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 + 30-Aug-05 RMS Revised to trim trailing spaces on file names + 25-Aug-05 RMS Added variable default device support + 23-Aug-05 RMS Added Linux line history support + 16-Aug-05 RMS Fixed C++ declaration and cast problems + 01-May-05 RMS Revised syntax for SET DEBUG (from Dave Bryan) + 22-Mar-05 JDB Modified DO command to allow ten-level nesting + 18-Mar-05 RMS Moved DETACH tests into detach_unit (from Dave Bryan) + Revised interface to fprint_sym, fparse_sym + 07-Feb-05 RMS Added ASSERT command (from Dave Bryan) + 02-Feb-05 RMS Fixed bug in global register search + 26-Dec-04 RMS Qualified SAVE examine, RESTORE deposit with SIM_SW_REST + 10-Nov-04 JDB Fixed logging of errors from cmds in "do" file + 05-Nov-04 RMS Moved SET/SHOW DEBUG under CONSOLE hierarchy + Renamed unit OFFLINE/ONLINE to DISABLED/ENABLED (from Dave Bryan) + Revised to flush output files after simulation stop (from Dave Bryan) + 15-Oct-04 RMS Fixed HELP to suppress duplicate descriptions + 27-Sep-04 RMS Fixed comma-separation options in set (from David Bryan) + 09-Sep-04 RMS Added -p option for RESET + 13-Aug-04 RMS Qualified RESTORE detach with SIM_SW_REST + 17-Jul-04 RMS Added ECHO command (from Dave Bryan) + 12-Jul-04 RMS Fixed problem ATTACHing to read only files + (found by John Dundas) + 28-May-04 RMS Added SET/SHOW CONSOLE + 14-Feb-04 RMS Updated SAVE/RESTORE (V3.2) + RMS Added debug print routines (from Dave Hittner) + RMS Added sim_vm_parse_addr and sim_vm_fprint_addr + RMS Added REG_VMAD support + RMS Split out libraries + RMS Moved logging function to SCP + RMS Exposed step counter interface(s) + RMS Fixed double logging of SHOW BREAK (found by Mark Pizzolato) + RMS Fixed implementation of REG_VMIO + RMS Added SET/SHOW DEBUG, SET/SHOW DEBUG, + SHOW MODIFIERS, SHOW RADIX + RMS Changed sim_fsize to take uptr argument + 29-Dec-03 RMS Added Telnet console output stall support + 01-Nov-03 RMS Cleaned up implicit detach on attach/restore + Fixed bug in command line read while logging (found by Mark Pizzolato) + 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" @@ -153,64 +157,69 @@ #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 */ +#if defined (HAVE_READLINE) +#include +#include +#endif -#define DO_NEST_LVL 10 /* DO cmd nesting level */ -#define SRBSIZ 1024 /* save/restore buffer */ -#define SIM_BRK_INILNT 4096 /* bpt tbl length */ -#define SIM_BRK_ALLTYP 0xFFFFFFFF +#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 DO_NEST_LVL 10 /* DO cmd nesting level */ +#define SRBSIZ 1024 /* save/restore buffer */ +#define SIM_BRK_INILNT 4096 /* bpt tbl length */ +#define SIM_BRK_ALLTYP 0xFFFFFFFF #define UPDATE_SIM_TIME(x) sim_time = sim_time + (x - sim_interval); \ - sim_rtime = sim_rtime + ((uint32) (x - sim_interval)); \ - x = sim_interval + sim_rtime = sim_rtime + ((uint32) (x - sim_interval)); \ + x = sim_interval #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]) + (size_map[((rp)->width + (rp)->offset + CHAR_BIT - 1) / CHAR_BIT]) #if defined (USE_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)); + 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; + 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)); + 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; + 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 + 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 (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; + /* VM interface */ extern char sim_name[]; @@ -221,9 +230,9 @@ 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); + UNIT *uptr, int32 sw); extern t_stat parse_sym (char *cptr, t_addr addr, UNIT *uptr, t_value *val, - int32 sw); + 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 */ @@ -234,7 +243,7 @@ void (*sim_vm_post) (t_bool from_scp) = NULL; CTAB *sim_vm_cmd = NULL; void (*sim_vm_fprint_addr) (FILE *st, DEVICE *dptr, t_addr addr) = NULL; t_addr (*sim_vm_parse_addr) (DEVICE *dptr, char *cptr, char **tptr) = NULL; - + /* Prototypes */ /* Set and show command processors */ @@ -293,6 +302,7 @@ 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); REG *find_reg_glob (char *ptr, char **optr, DEVICE **gdptr); +char *sim_trim_endspc (char *cptr); /* Forward references within commands */ @@ -304,19 +314,20 @@ 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); + 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_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); + 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 */ +DEVICE *sim_dflt_dev = NULL; UNIT *sim_clock_queue = NULL; int32 sim_interval = 0; int32 sim_switches = 0; @@ -342,184 +353,185 @@ static uint32 sim_rtime; static int32 noqueue_time; volatile int32 stop_cpu = 0; t_value *sim_eval = NULL; -int32 sim_deb_close = 0; /* 1 = close debug */ -FILE *sim_log = NULL; /* log file */ -FILE *sim_deb = NULL; /* debug file */ +int32 sim_deb_close = 0; /* 1 = close debug */ +FILE *sim_log = NULL; /* log file */ +FILE *sim_deb = NULL; /* debug file */ static SCHTAB sim_stab; static UNIT sim_step_unit = { UDATA (&step_svc, 0, 0) }; - + /* Tables and strings */ const char save_vercur[] = "V3.2"; const char save_ver30[] = "V3.0"; const char save_ver210[] = "V2.10"; 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 command limit exceeded", - "Internal error", - "Invalid magtape record length", - "Console Telnet connection lost", - "Console Telnet connection timed out", - "Console Telnet output stall", - "" /* printed by assert */ - }; + "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 command limit exceeded", + "Internal error", + "Invalid magtape record length", + "Console Telnet connection lost", + "Console Telnet connection timed out", + "Console Telnet output stall", + "" /* printed by assert */ + }; const size_t size_map[] = { sizeof (int8), - sizeof (int8), sizeof (int16), sizeof (int32), sizeof (int32) + sizeof (int8), sizeof (int16), sizeof (int32), sizeof (int32) #if defined (USE_INT64) - , sizeof (t_int64), sizeof (t_int64), sizeof (t_int64), sizeof (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 + 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 (USE_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 + , 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 console arg{,arg...} set console options\n" - "set OCT|DEC|HEX set device display radix\n" - "set ENABLED enable device\n" - "set DISABLED disable device\n" - "set DEBUG{=arg} set device debug flags\n" - "set NODEBUG={arg} clear device debug flags\n" - "set arg{,arg...} set device parameters\n" - "set ENABLED enable unit\n" - "set DISABLED disable unit\n" - "set arg{,arg...} set unit parameters\n" - }, - { "SHOW", &show_cmd, 0, - "sh{ow} br{eak} show breakpoints on address list\n" - "sh{ow} con{figuration} show configuration\n" - "sh{ow} cons{ole} {arg} show console options\n" - "sh{ow} dev{ices} show devices\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} ti{me} show simulated time\n" - "sh{ow} ve{rsion} show simulator version\n" - "sh{ow} RADIX show device display radix\n" - "sh{ow} DEBUG show device debug flags\n" - "sh{ow} MODIFIERS show device modifiers\n" - "sh{ow} {arg,...} show device parameters\n" - "sh{ow} {arg,...} show unit parameters\n" }, - { "DO", &do_cmd, 1, - "do {arg,arg...} process command file\n" }, - { "ECHO", &echo_cmd, 0, - "echo display \n" }, - { "ASSERT", &assert_cmd, 0, - "assert {} test simulator state against condition\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 } }; - + { "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 console arg{,arg...} set console options\n" + "set OCT|DEC|HEX set device display radix\n" + "set ENABLED enable device\n" + "set DISABLED disable device\n" + "set DEBUG{=arg} set device debug flags\n" + "set NODEBUG={arg} clear device debug flags\n" + "set arg{,arg...} set device parameters\n" + "set ENABLED enable unit\n" + "set DISABLED disable unit\n" + "set arg{,arg...} set unit parameters\n" + }, + { "SHOW", &show_cmd, 0, + "sh{ow} br{eak} show breakpoints on address list\n" + "sh{ow} con{figuration} show configuration\n" + "sh{ow} cons{ole} {arg} show console options\n" + "sh{ow} dev{ices} show devices\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} ti{me} show simulated time\n" + "sh{ow} ve{rsion} show simulator version\n" + "sh{ow} RADIX show device display radix\n" + "sh{ow} DEBUG show device debug flags\n" + "sh{ow} MODIFIERS show device modifiers\n" + "sh{ow} {arg,...} show device parameters\n" + "sh{ow} {arg,...} show unit parameters\n" }, + { "DO", &do_cmd, 1, + "do {arg,arg...} process command file\n" }, + { "ECHO", &echo_cmd, 0, + "echo display \n" }, + { "ASSERT", &assert_cmd, 0, + "assert {} test simulator state against condition\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[]) @@ -534,27 +546,32 @@ CTAB *cmdp; argc = ccommand (&argv); #endif -*cbuf = 0; /* init arg buffer */ -sim_switches = 0; /* init switches */ +*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 */ +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 */ -sim_finit (); /* init fio package */ +if (sim_vm_init != NULL) (*sim_vm_init)(); /* call once only */ +sim_finit (); /* init fio package */ stop_cpu = 0; sim_interval = 0; sim_time = sim_rtime = 0; @@ -565,63 +582,72 @@ sim_log = NULL; if (sim_emax <= 0) sim_emax = 1; if ((stat = sim_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; }; + fprintf (stderr, "Fatal terminal initialization error\n%s\n", + scp_error_messages[stat - SCPE_BASE]); + return 0; + } +if ((sim_eval = (t_value *) calloc (sim_emax, sizeof (t_value))) == NULL) { + fprintf (stderr, "Unable to allocate examine buffer\n"); + return 0; + }; if ((stat = reset_all_p (0)) != SCPE_OK) { - fprintf (stderr, "Fatal simulator initialization error\n%s\n", - scp_error_messages[stat - SCPE_BASE]); - return 0; } + 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; } + 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, NULL, NULL, 0, NULL); } + printf ("\n"); + show_version (stdout, NULL, NULL, 0, NULL); + } +if (sim_dflt_dev == NULL) sim_dflt_dev = sim_devices[0]; /* if no default */ -if (*cbuf) { /* cmd file arg? */ - stat = do_cmd (0, 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 (0, nbuf); } /* proc cmd file */ +if (*cbuf) { /* cmd file arg? */ + stat = do_cmd (0, 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 (0, 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 */ +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 */ -sim_set_deboff (0, NULL); /* close debug */ -sim_set_logoff (0, NULL); /* close log */ -sim_set_notelnet (0, NULL); /* close Telnet */ -sim_ttclose (); /* close console */ +detach_all (0, TRUE); /* close files */ +sim_set_deboff (0, NULL); /* close debug */ +sim_set_logoff (0, NULL); /* close log */ +sim_set_notelnet (0, NULL); /* close Telnet */ +sim_ttclose (); /* close console */ return 0; } @@ -631,11 +657,11 @@ 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 */ +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) @@ -650,10 +676,12 @@ void fprint_help (FILE *st) CTAB *cmdp; for (cmdp = sim_vm_cmd; cmdp && (cmdp->name != NULL); cmdp++) { - if (cmdp->help) fprintf (st, cmdp->help); } + if (cmdp->help) fprintf (st, cmdp->help); + } for (cmdp = cmd_table; cmdp && (cmdp->name != NULL); cmdp++) { - if (cmdp->help && (!sim_vm_cmd || !find_ctab (sim_vm_cmd, cmdp->name))) - fprintf (st, cmdp->help); } + if (cmdp->help && (!sim_vm_cmd || !find_ctab (sim_vm_cmd, cmdp->name))) + fprintf (st, cmdp->help); + } return; } @@ -664,14 +692,18 @@ 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); } + 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; } @@ -684,8 +716,8 @@ 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 */ +fflush(stdout); /* flush stdout */ +if (sim_log) fflush (sim_log); /* flush log if enabled */ system (cptr); #if defined (VMS) printf ("\n"); @@ -702,7 +734,7 @@ puts (cptr); if (sim_log) fprintf (sim_log, "%s\n", cptr); return SCPE_OK; } - + /* Do command */ t_stat do_cmd (int32 flag, char *fcptr) @@ -713,58 +745,61 @@ CTAB *cmdp; int32 echo, nargs; t_stat stat = SCPE_OK; -if (flag > 0) { GET_SWITCHES (fcptr); } /* get switches */ -else flag = 1; /* start at level 1 */ -echo = sim_switches & SWMASK ('V'); /* -v means echo */ +if (flag > 0) { GET_SWITCHES (fcptr); } /* get switches */ +else flag = 1; /* start at level 1 */ +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; +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 (echo && sim_log) fprintf (sim_log, "do> %s\n", cptr); - cptr = get_glyph (cptr, gbuf, 0); /* get command glyph */ - sim_switches = 0; /* init switches */ - if (cmdp = find_cmd (gbuf)) { /* lookup command */ - if (cmdp->action == &do_cmd) /* DO command? */ - if (flag >= DO_NEST_LVL) /* nest too deep? */ - stat = SCPE_NEST; - else stat = do_cmd (flag + 1, cptr); /* exec DO cmd */ - else stat = cmdp->action (cmdp->arg, cptr); } /* exec other cmd */ - else stat = SCPE_UNK; /* bad cmd given */ - 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); -} while ((stat != SCPE_EXIT) && (stat != SCPE_AFAIL)); +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 (echo && sim_log) fprintf (sim_log, "do> %s\n", cptr); + cptr = get_glyph (cptr, gbuf, 0); /* get command glyph */ + sim_switches = 0; /* init switches */ + if (cmdp = find_cmd (gbuf)) { /* lookup command */ + if (cmdp->action == &do_cmd) { /* DO command? */ + if (flag >= DO_NEST_LVL) stat = SCPE_NEST; /* nest too deep? */ + else stat = do_cmd (flag + 1, cptr); /* exec DO cmd */ + } + else stat = cmdp->action (cmdp->arg, cptr); /* exec other cmd */ + } + else stat = SCPE_UNK; /* bad cmd given */ + 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); + } while ((stat != SCPE_EXIT) && (stat != SCPE_AFAIL)); -fclose (fpin); /* close file */ +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 + 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[]) @@ -772,16 +807,19 @@ void sub_args (char *instr, char *tmpbuf, int32 maxstr, int32 nargs, char *do_ar 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 */ + 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; } @@ -802,34 +840,35 @@ uint32 idx; t_value val; t_stat r; -aptr = cptr; /* save assertion */ -cptr = get_sim_opt (CMD_OPT_SW|CMD_OPT_DFT, cptr, &r); /* get sw, default */ -if (*cptr == 0) return SCPE_2FARG; /* must be more */ -cptr = get_glyph (cptr, gbuf, 0); /* get register */ -rptr = find_reg (gbuf, &gptr, sim_dfdev); /* parse register */ -if (!rptr) return SCPE_NXREG; /* not there */ -if (*gptr == '[') { /* subscript? */ - if (rptr->depth <= 1) return SCPE_ARG; /* array register? */ - idx = (uint32) strtotv (++gptr, &tptr, 10); /* convert index */ - if ((gptr == tptr) || (*tptr++ != ']')) return SCPE_ARG; - gptr = tptr; /* update */ - } -else idx = 0; /* not array */ -if (idx >= rptr->depth) return SCPE_SUB; /* validate subscript */ -if (*gptr != 0) get_glyph (gptr, gbuf, 0); /* more? must be search */ -else { if (*cptr == 0) return SCPE_2FARG; /* must be more */ - cptr = get_glyph (cptr, gbuf, 0); /* get search cond */ - } -if (*cptr != 0) return SCPE_2MARG; /* must be done */ -if (!get_search (gbuf, rptr->radix, &sim_stab)) /* parse condition */ - return SCPE_MISVAL; -val = get_rval (rptr, idx); /* get register value */ -if (test_search (val, &sim_stab)) return SCPE_OK; /* test condition */ -printf ("Assertion failed (%s)", aptr); /* report failing assertion */ +aptr = cptr; /* save assertion */ +cptr = get_sim_opt (CMD_OPT_SW|CMD_OPT_DFT, cptr, &r); /* get sw, default */ +if (*cptr == 0) return SCPE_2FARG; /* must be more */ +cptr = get_glyph (cptr, gbuf, 0); /* get register */ +rptr = find_reg (gbuf, &gptr, sim_dfdev); /* parse register */ +if (!rptr) return SCPE_NXREG; /* not there */ +if (*gptr == '[') { /* subscript? */ + if (rptr->depth <= 1) return SCPE_ARG; /* array register? */ + idx = (uint32) strtotv (++gptr, &tptr, 10); /* convert index */ + if ((gptr == tptr) || (*tptr++ != ']')) return SCPE_ARG; + gptr = tptr; /* update */ + } +else idx = 0; /* not array */ +if (idx >= rptr->depth) return SCPE_SUB; /* validate subscript */ +if (*gptr != 0) get_glyph (gptr, gbuf, 0); /* more? must be search */ +else { + if (*cptr == 0) return SCPE_2FARG; /* must be more */ + cptr = get_glyph (cptr, gbuf, 0); /* get search cond */ + } +if (*cptr != 0) return SCPE_2MARG; /* must be done */ +if (!get_search (gbuf, rptr->radix, &sim_stab)) /* parse condition */ + return SCPE_MISVAL; +val = get_rval (rptr, idx); /* get register value */ +if (test_search (val, &sim_stab)) return SCPE_OK; /* test condition */ +printf ("Assertion failed (%s)", aptr); /* report failing assertion */ if (sim_log) fprintf (sim_log, "Assertion failed (%s)", aptr); -return SCPE_AFAIL; /* condition fails */ +return SCPE_AFAIL; /* condition fails */ } - + /* Set command */ t_stat set_cmd (int32 flag, char *cptr) @@ -844,107 +883,118 @@ CTAB *gcmdp; C1TAB *ctbr, *glbr; static CTAB set_glob_tab[] = { - { "CONSOLE", &sim_set_console, 0 }, - { "BREAK", &brk_cmd, SSH_ST }, - { "TELNET", &sim_set_telnet, 0 }, /* deprecated */ - { "NOTELNET", &sim_set_notelnet, 0 }, /* deprecated */ - { "LOG", &sim_set_logon, 0 }, /* deprecated */ - { "NOLOG", &sim_set_logoff, 0 }, /* deprecated */ - { "DEBUG", &sim_set_debon, 0 }, /* deprecated */ - { "NODEBUG", &sim_set_deboff, 0 }, /* deprecated */ - { NULL, NULL, 0 } }; + { "CONSOLE", &sim_set_console, 0 }, + { "BREAK", &brk_cmd, SSH_ST }, + { "TELNET", &sim_set_telnet, 0 }, /* deprecated */ + { "NOTELNET", &sim_set_notelnet, 0 }, /* deprecated */ + { "LOG", &sim_set_logon, 0 }, /* deprecated */ + { "NOLOG", &sim_set_logoff, 0 }, /* deprecated */ + { "DEBUG", &sim_set_debon, 0 }, /* deprecated */ + { "NODEBUG", &sim_set_deboff, 0 }, /* deprecated */ + { NULL, NULL, 0 } + }; static C1TAB set_dev_tab[] = { - { "OCTAL", &set_dev_radix, 8 }, - { "DECIMAL", &set_dev_radix, 10 }, - { "HEX", &set_dev_radix, 16 }, - { "ENABLED", &set_dev_enbdis, 1 }, - { "DISABLED", &set_dev_enbdis, 0 }, - { "DEBUG", &set_dev_debug, 1 }, - { "NODEBUG", &set_dev_debug, 0 }, - { NULL, NULL, 0 } }; + { "OCTAL", &set_dev_radix, 8 }, + { "DECIMAL", &set_dev_radix, 10 }, + { "HEX", &set_dev_radix, 16 }, + { "ENABLED", &set_dev_enbdis, 1 }, + { "DISABLED", &set_dev_enbdis, 0 }, + { "DEBUG", &set_dev_debug, 1 }, + { "NODEBUG", &set_dev_debug, 0 }, + { NULL, NULL, 0 } + }; static C1TAB set_unit_tab[] = { - { "ENABLED", &set_unit_enbdis, 1 }, - { "DISABLED", &set_unit_enbdis, 0 }, - { NULL, NULL, 0 } }; + { "ENABLED", &set_unit_enbdis, 1 }, + { "DISABLED", &set_unit_enbdis, 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 */ +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 */ +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? */ +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, cvptr); /* 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 */ + 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, cvptr); /* 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; } + 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; } + if (MATCH_CMD (gbuf, tab->name) == 0) return tab; + } return NULL; } @@ -966,17 +1016,21 @@ uint32 i; if (cptr) return SCPE_ARG; if ((dptr->flags & DEV_DISABLE) == 0) return SCPE_NOFNC;/* allowed? */ -if (flag) { /* enable? */ - if ((dptr->flags & DEV_DIS) == 0) /* already enb? ok */ - return SCPE_OK; - dptr->flags = dptr->flags & ~DEV_DIS; } /* no, enable */ -else { 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 */ +if (flag) { /* enable? */ + if ((dptr->flags & DEV_DIS) == 0) /* already enb? ok */ + return SCPE_OK; + dptr->flags = dptr->flags & ~DEV_DIS; /* no, enable */ + } +else { + 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; } @@ -985,11 +1039,13 @@ else return SCPE_OK; t_stat set_unit_enbdis (DEVICE *dptr, UNIT *uptr, int32 flag, char *cptr) { if (cptr) return SCPE_ARG; -if (!(uptr->flags & UNIT_DISABLE)) return SCPE_NOFNC; /* allowed? */ -if (flag) uptr->flags = uptr->flags & ~UNIT_DIS; /* enb? enable */ -else { if ((uptr->flags & UNIT_ATT) || /* dsb */ - sim_is_active (uptr)) return SCPE_NOFNC; /* more tests */ - uptr->flags = uptr->flags | UNIT_DIS; } /* disable */ +if (!(uptr->flags & UNIT_DISABLE)) return SCPE_NOFNC; /* allowed? */ +if (flag) uptr->flags = uptr->flags & ~UNIT_DIS; /* enb? enable */ +else { + if ((uptr->flags & UNIT_ATT) || /* dsb */ + sim_is_active (uptr)) return SCPE_NOFNC; /* more tests */ + uptr->flags = uptr->flags | UNIT_DIS; /* disable */ + } return SCPE_OK; } @@ -1001,39 +1057,45 @@ char gbuf[CBUFSIZE]; DEBTAB *dep; if ((dptr->flags & DEV_DEBUG) == 0) return SCPE_NOFNC; -if (cptr == NULL) { /* no arguments? */ - dptr->dctrl = flag; /* disable/enable w/o table */ - if (flag && dptr->debflags) { /* enable with table? */ - for (dep = dptr->debflags; dep->name != NULL; dep++) - dptr->dctrl = dptr->dctrl | dep->mask; } /* set all */ - return SCPE_OK; } -if (dptr->debflags == NULL) return SCPE_ARG; /* must have table */ +if (cptr == NULL) { /* no arguments? */ + dptr->dctrl = flag; /* disable/enable w/o table */ + if (flag && dptr->debflags) { /* enable with table? */ + for (dep = dptr->debflags; dep->name != NULL; dep++) + dptr->dctrl = dptr->dctrl | dep->mask; /* set all */ + } + return SCPE_OK; + } +if (dptr->debflags == NULL) return SCPE_ARG; /* must have table */ while (*cptr) { - cptr = get_glyph (cptr, gbuf, ';'); /* get debug flag */ - for (dep = dptr->debflags; dep->name != NULL; dep++) { - if (strcmp (dep->name, gbuf) == 0) { /* match? */ - if (flag) dptr->dctrl = dptr->dctrl | dep->mask; - else dptr->dctrl = dptr->dctrl & ~dep->mask; - break; } - } /* end for */ - if (dep->mask == 0) return SCPE_ARG; /* no match? */ - } /* end while */ + cptr = get_glyph (cptr, gbuf, ';'); /* get debug flag */ + for (dep = dptr->debflags; dep->name != NULL; dep++) { + if (strcmp (dep->name, gbuf) == 0) { /* match? */ + if (flag) dptr->dctrl = dptr->dctrl | dep->mask; + else dptr->dctrl = dptr->dctrl & ~dep->mask; + break; + } + } /* end for */ + if (dep->mask == 0) return SCPE_ARG; /* no match? */ + } /* end while */ return SCPE_OK; } - + /* Show command */ t_stat show_cmd (int32 flag, char *cptr) { t_stat r; -cptr = get_sim_opt (CMD_OPT_SW|CMD_OPT_OF, cptr, &r); /* get sw, ofile */ -if (!cptr) return r; /* error? */ -if (sim_ofile) { /* output file? */ - r = show_cmd_fi (sim_ofile, flag, cptr); /* do show */ - fclose (sim_ofile); } -else { r = show_cmd_fi (stdout, flag, cptr); /* no, stdout, log */ - if (sim_log) show_cmd_fi (sim_log, flag, cptr); } +cptr = get_sim_opt (CMD_OPT_SW|CMD_OPT_OF, cptr, &r); /* get sw, ofile */ +if (!cptr) return r; /* error? */ +if (sim_ofile) { /* output file? */ + r = show_cmd_fi (sim_ofile, flag, cptr); /* do show */ + fclose (sim_ofile); + } +else { + r = show_cmd_fi (stdout, flag, cptr); /* no, stdout, log */ + if (sim_log) show_cmd_fi (sim_log, flag, cptr); + } return r; } @@ -1047,85 +1109,92 @@ MTAB *mptr; SHTAB *shtb, *shptr; static SHTAB show_glob_tab[] = { - { "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, 1 }, - { "CONSOLE", &sim_show_console, 0 }, - { "BREAK", &show_break, 0 }, - { "LOG", &sim_show_log, 0 }, /* deprecated */ - { "TELNET", &sim_show_telnet, 0 }, /* deprecated */ - { "DEBUG", &sim_show_debug, 0 }, /* deprecated */ - { NULL, NULL, 0 } }; + { "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, 1 }, + { "CONSOLE", &sim_show_console, 0 }, + { "BREAK", &show_break, 0 }, + { "LOG", &sim_show_log, 0 }, /* deprecated */ + { "TELNET", &sim_show_telnet, 0 }, /* deprecated */ + { "DEBUG", &sim_show_debug, 0 }, /* deprecated */ + { NULL, NULL, 0 } + }; static SHTAB show_dev_tab[] = { - { "RADIX", &show_dev_radix, 0 }, - { "DEBUG", &show_dev_debug, 0 }, - { "MODIFIERS", &show_dev_modifiers, 0 }, - { "NAMES", &show_dev_logicals, 0 }, - { NULL, NULL, 0 } }; + { "RADIX", &show_dev_radix, 0 }, + { "DEBUG", &show_dev_debug, 0 }, + { "MODIFIERS", &show_dev_modifiers, 0 }, + { "NAMES", &show_dev_logicals, 0 }, + { NULL, NULL, 0 } + }; static SHTAB show_unit_tab[] = { - { NULL, NULL, 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 */ -if (shptr = find_shtab (show_glob_tab, gbuf)) /* global? */ - return shptr->action (ofile, NULL, NULL, shptr->arg, cptr); +GET_SWITCHES (cptr); /* get switches */ +if (*cptr == 0) return SCPE_2FARG; /* must be more */ +cptr = get_glyph (cptr, gbuf, 0); /* get next glyph */ +if (shptr = find_shtab (show_glob_tab, gbuf)) /* global? */ + return shptr->action (ofile, NULL, NULL, shptr->arg, cptr); -if (dptr = find_dev (gbuf)) { /* device match? */ - uptr = dptr->units; /* first unit */ - shtb = show_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 */ - if (uptr->flags & UNIT_DIS) return SCPE_UDIS; /* disabled? */ - shtb = show_unit_tab; /* global table */ - lvl = MTAB_VUN; } /* unit match */ -else return SCPE_NXDEV; /* no match */ +if (dptr = find_dev (gbuf)) { /* device match? */ + uptr = dptr->units; /* first unit */ + shtb = show_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 */ + if (uptr->flags & UNIT_DIS) return SCPE_UDIS; /* disabled? */ + shtb = show_unit_tab; /* global table */ + lvl = MTAB_VUN; /* unit match */ + } +else return SCPE_NXDEV; /* no match */ -if (*cptr == 0) { /* now eol? */ - return (lvl == MTAB_VDV)? - show_device (ofile, dptr, 0): - show_unit (ofile, dptr, uptr, -1); } -if (dptr->modifiers == NULL) return SCPE_NOPARAM; /* any modifiers? */ +if (*cptr == 0) { /* now eol? */ + return (lvl == MTAB_VDV)? + show_device (ofile, dptr, 0): + show_unit (ofile, dptr, uptr, -1); + } +if (dptr->modifiers == NULL) return SCPE_NOPARAM; /* any modifiers? */ -while (*cptr != 0) { /* do all mods */ - cptr = get_glyph (cptr, gbuf, ','); /* get modifier */ - if (cvptr = strchr (gbuf, '=')) *cvptr++ = 0; /* = value? */ - 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)))) { - if (cvptr && !(mptr->mask & MTAB_SHP)) return SCPE_ARG; - show_one_mod (ofile, dptr, uptr, mptr, cvptr, 1); - break; - } /* end if */ - } /* end for */ - if (mptr->mask == 0) { /* no match? */ - if (shptr = find_shtab (shtb, gbuf)) /* global match? */ - shptr->action (ofile, dptr, uptr, shptr->arg, cptr); - else return SCPE_ARG; - } /* end if */ - } /* end while */ +while (*cptr != 0) { /* do all mods */ + cptr = get_glyph (cptr, gbuf, ','); /* get modifier */ + if (cvptr = strchr (gbuf, '=')) *cvptr++ = 0; /* = value? */ + 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)))) { + if (cvptr && !(mptr->mask & MTAB_SHP)) return SCPE_ARG; + show_one_mod (ofile, dptr, uptr, mptr, cvptr, 1); + break; + } /* end if */ + } /* end for */ + if (mptr->mask == 0) { /* no match? */ + if (shptr = find_shtab (shtb, gbuf)) /* global match? */ + shptr->action (ofile, dptr, uptr, shptr->arg, cptr); + else return SCPE_ARG; + } /* end if */ + } /* end while */ return SCPE_OK; } SHTAB *find_shtab (SHTAB *tab, char *gbuf) { for (; tab->name != NULL; tab++) { - if (MATCH_CMD (gbuf, tab->name) == 0) return tab; } + if (MATCH_CMD (gbuf, tab->name) == 0) return tab; + } return NULL; } - + /* Show device and unit */ t_stat show_device (FILE *st, DEVICE *dptr, int32 flag) @@ -1133,24 +1202,29 @@ t_stat show_device (FILE *st, DEVICE *dptr, int32 flag) uint32 j, udbl, 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 = udbl = 0; j < dptr->numunits; j++) { /* count units */ - uptr = dptr->units + j; - if (uptr->flags & UNIT_DISABLE) udbl++; - if (!(uptr->flags & UNIT_DIS)) ucnt++; } -show_all_mods (st, dptr, dptr->units, MTAB_VDV); /* show dev mods */ +fprintf (st, "%s", sim_dname (dptr)); /* print dev name */ +if (qdisable (dptr)) { /* disabled? */ + fprintf (st, ", disabled\n"); + return SCPE_OK; + } +for (j = ucnt = udbl = 0; j < dptr->numunits; j++) { /* count units */ + uptr = dptr->units + j; + if (uptr->flags & UNIT_DISABLE) udbl++; + 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 (udbl && (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); } +else { + if (udbl && (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; } @@ -1161,14 +1235,16 @@ 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); } + 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"); } + 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, ", not attached"); +show_all_mods (st, dptr, uptr, MTAB_VUN); /* show unit mods */ fprintf (st, "\n"); return SCPE_OK; } @@ -1184,16 +1260,19 @@ 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; } + 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, DEVICE *dptr, UNIT *uptr, int32 flag, char *cptr) @@ -1230,7 +1309,7 @@ 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); + show_device (st, dptr, flag); return SCPE_OK; } @@ -1241,7 +1320,7 @@ DEVICE *dptr; if (cptr && (*cptr != 0)) return SCPE_2MARG; for (i = 0; (dptr = sim_devices[i]) != NULL; i++) - show_dev_logicals (st, dptr, NULL, 1, cptr); + show_dev_logicals (st, dptr, NULL, 1, cptr); return SCPE_OK; } @@ -1260,28 +1339,31 @@ 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 empty, time = %.0f\n", + sim_name, sim_time); + return SCPE_OK; + } fprintf (st, "%s event queue status, time = %.0f\n", - sim_name, sim_time); + sim_name, sim_time); accum = 0; for (uptr = sim_clock_queue; uptr != NULL; uptr = uptr->next) { - if (uptr == &sim_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; } + if (uptr == &sim_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", + (int32) (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, DEVICE *dptr, UNIT *uptr, int32 flag, char *cptr) { if (cptr && (*cptr != 0)) return SCPE_2MARG; -fprintf (st, "Time: %.0f\n", sim_time); +fprintf (st, "Time:\t%.0f\n", sim_time); return SCPE_OK; } @@ -1289,7 +1371,7 @@ t_stat show_break (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, char *cptr) { t_stat r; -if (cptr && (*cptr != 0)) r = ssh_break (st, cptr, 1); /* more? */ +if (cptr && (*cptr != 0)) r = ssh_break (st, cptr, 1); /* more? */ else r = sim_brk_showall (st, sim_switches); return r; } @@ -1306,23 +1388,24 @@ int32 any = 0; DEBTAB *dep; if (dptr->flags & DEV_DEBUG) { - if (dptr->dctrl == 0) fputs ("Debugging disabled", st); - else if (dptr->debflags == NULL) fputs ("Debugging enabled", st); - else { - fputs ("Debug=", st); - for (dep = dptr->debflags; dep->name != NULL; dep++) { - if (dptr->dctrl & dep->mask) { - if (any) fputc (';', st); - fputs (dep->name, st); - any = 1; } - } - } - fputc ('\n', st); - return SCPE_OK; - } + if (dptr->dctrl == 0) fputs ("Debugging disabled", st); + else if (dptr->debflags == NULL) fputs ("Debugging enabled", st); + else { + fputs ("Debug=", st); + for (dep = dptr->debflags; dep->name != NULL; dep++) { + if (dptr->dctrl & dep->mask) { + if (any) fputc (';', st); + fputs (dep->name, st); + any = 1; + } + } + } + fputc ('\n', st); + return SCPE_OK; + } else return SCPE_NOFNC; } - + /* Show modifiers */ t_stat show_mod_names (FILE *st, DEVICE *dnotused, UNIT *unotused, int32 flag, char *cptr) @@ -1330,9 +1413,9 @@ t_stat show_mod_names (FILE *st, DEVICE *dnotused, UNIT *unotused, int32 flag, c int32 i; DEVICE *dptr; -if (cptr && (*cptr != 0)) return SCPE_2MARG; /* now eol? */ +if (cptr && (*cptr != 0)) return SCPE_2MARG; /* now eol? */ for (i = 0; (dptr = sim_devices[i]) != NULL; i++) - show_dev_modifiers (st, dptr, NULL, flag, cptr); + show_dev_modifiers (st, dptr, NULL, flag, cptr); return SCPE_OK; } @@ -1344,23 +1427,29 @@ DEBTAB *dep; 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); } } } + 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 (dptr->flags & DEV_DEBUG) { - if (any++) fprintf (st, ", DEBUG, NODEBUG"); - else fprintf (st, "%s\tDEBUG, NODEBUG", sim_dname (dptr)); } + if (any++) fprintf (st, ", DEBUG, NODEBUG"); + else fprintf (st, "%s\tDEBUG, NODEBUG", sim_dname (dptr)); + } 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, ", ENABLED, DISABLED"); + else fprintf (st, "%s\tENABLED, DISABLED", sim_dname (dptr)); + } if (any) fprintf (st, "\n"); if ((dptr->flags & DEV_DEBUG) && dptr->debflags) { - fprintf (st, "%s\tDEBUG=", sim_dname (dptr)); - for (dep = dptr->debflags; dep->name != NULL; dep++) - fprintf (st, "%s%s", ((dep == dptr->debflags) ? "" : ","), dep->name); - fprintf (st, "\n"); } + fprintf (st, "%s\tDEBUG=", sim_dname (dptr)); + for (dep = dptr->debflags; dep->name != NULL; dep++) + fprintf (st, "%s%s", ((dep == dptr->debflags) ? "" : ","), dep->name); + fprintf (st, "\n"); + } return SCPE_OK; } @@ -1370,44 +1459,47 @@ 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, NULL, 0); } } + 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, NULL, 0); + } + } return SCPE_OK; } t_stat show_one_mod (FILE *st, DEVICE *dptr, UNIT *uptr, MTAB *mptr, - char *cptr, int32 flag) + char *cptr, int32 flag) { t_value val; if (mptr->disp) mptr->disp (st, uptr, mptr->match, cptr? cptr: 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); } + 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 */ +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]; +DEVICE *dptr = sim_dflt_dev; UNIT *uptr = dptr->units; t_stat r; t_addr lo, hi, max = uptr->capac - 1; @@ -1416,51 +1508,59 @@ 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 */ +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 (dptr, 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 + 1) { - switch (flg) { - case SSH_ST: - r = sim_brk_set (lo, sim_switches, cnt, aptr); - break; - case SSH_CL: - r = sim_brk_clr (lo, sim_switches); - break; - case SSH_SH: - r = sim_brk_show (st, lo, sim_switches); - break; - default: - return SCPE_ARG; - } - if (r != SCPE_OK) return r; - } - } - } + cptr = get_glyph (cptr, gbuf, ','); + tptr = get_range (dptr, 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 + 1) { + switch (flg) { + + case SSH_ST: + r = sim_brk_set (lo, sim_switches, cnt, aptr); + break; + + case SSH_CL: + r = sim_brk_clr (lo, sim_switches); + break; + + case SSH_SH: + r = sim_brk_show (st, lo, sim_switches); + break; + + default: + 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 + 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) @@ -1468,13 +1568,13 @@ 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? */ +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? */ +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; } @@ -1482,9 +1582,9 @@ else return SCPE_OK; /* Reset devices start..end Inputs: - start = number of starting device + start = number of starting device Outputs: - status = error status + status = error status */ t_stat reset_all (uint32 start) @@ -1494,20 +1594,23 @@ uint32 i; t_stat reason; for (i = 0; i < start; i++) { - if (sim_devices[i] == NULL) return SCPE_IERR; } + 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; } } + if (dptr->reset != NULL) { + reason = dptr->reset (dptr); + if (reason != SCPE_OK) return reason; + } + } return SCPE_OK; } /* Reset to powerup state Inputs: - start = number of starting device + start = number of starting device Outputs: - status = error status + status = error status */ t_stat reset_all_p (uint32 start) @@ -1520,11 +1623,11 @@ r = reset_all (start); sim_switches = old_sw; return r; } - + /* Load and dump commands - lo[ad] filename {arg} load specified file - du[mp] filename {arg} dump to specified file + lo[ad] filename {arg} load specified file + du[mp] filename {arg} dump to specified file */ t_stat load_cmd (int32 flag, char *cptr) @@ -1533,20 +1636,20 @@ 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 = sim_fopen (gbuf, flag? "wb": "rb"); /* open for wr/rd */ +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 = sim_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 */ +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 + at[tach] unit file attach specified unit to file */ t_stat attach_cmd (int32 flag, char *cptr) @@ -1556,27 +1659,29 @@ DEVICE *dptr; UNIT *uptr; t_stat r; -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 (uptr->flags & UNIT_ATT) { /* already attached? */ - r = scp_detach_unit (dptr, uptr); /* detach it */ - if (r != SCPE_OK) return r; } /* error? */ -return scp_attach_unit (dptr, uptr, cptr); /* attach */ +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 (uptr->flags & UNIT_ATT) { /* already attached? */ + r = scp_detach_unit (dptr, uptr); /* detach it */ + if (r != SCPE_OK) return r; /* error? */ + } +sim_trim_endspc (cptr); /* trim trailing spc */ +return scp_attach_unit (dptr, uptr, cptr); /* attach */ } /* Call device-specific or file-oriented attach unit routine */ t_stat scp_attach_unit (DEVICE *dptr, UNIT *uptr, char *cptr) { -if (dptr->attach != NULL) /* device routine? */ - return dptr->attach (uptr, cptr); /* call it */ -return attach_unit (uptr, cptr); /* no, std routine */ +if (dptr->attach != NULL) /* device routine? */ + return dptr->attach (uptr, cptr); /* call it */ +return attach_unit (uptr, cptr); /* no, std routine */ } /* Attach unit to file */ @@ -1585,51 +1690,55 @@ t_stat attach_unit (UNIT *uptr, char *cptr) { DEVICE *dptr; -if (uptr->flags & UNIT_DIS) return SCPE_UDIS; /* disabled? */ -if (!(uptr->flags & UNIT_ATTABLE)) return SCPE_NOATT; /* not attachable? */ +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 (dptr->flags & DEV_RAWONLY) return SCPE_NOFNC; /* raw mode only? */ -uptr->filename = calloc (CBUFSIZE, sizeof (char)); /* alloc buf for name */ +if (dptr->flags & DEV_RAWONLY) return SCPE_NOFNC; /* raw mode only? */ +uptr->filename = (char *) calloc (CBUFSIZE, sizeof (char)); /* alloc name buf */ if (uptr->filename == NULL) return SCPE_MEM; -strncpy (uptr->filename, cptr, CBUFSIZE); /* save name */ -if (sim_switches & SWMASK ('R')) { /* read only? */ - if ((uptr->flags & UNIT_ROABLE) == 0) /* allowed? */ - return attach_err (uptr, SCPE_NORO); /* no, error */ - uptr->fileref = sim_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 = sim_fopen (cptr, "rb+"); /* open r/w */ - if (uptr->fileref == NULL) { /* open fail? */ - if ((errno == EROFS) || (errno == EACCES)) { /* read only? */ - if ((uptr->flags & UNIT_ROABLE) == 0) /* allowed? */ - return attach_err (uptr, SCPE_NORO); /* no error */ - uptr->fileref = sim_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 = sim_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 */ +strncpy (uptr->filename, cptr, CBUFSIZE); /* save name */ +if (sim_switches & SWMASK ('R')) { /* read only? */ + if ((uptr->flags & UNIT_ROABLE) == 0) /* allowed? */ + return attach_err (uptr, SCPE_NORO); /* no, error */ + uptr->fileref = sim_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 = sim_fopen (cptr, "rb+"); /* open r/w */ + if (uptr->fileref == NULL) { /* open fail? */ + if ((errno == EROFS) || (errno == EACCES)) { /* read only? */ + if ((uptr->flags & UNIT_ROABLE) == 0) /* allowed? */ + return attach_err (uptr, SCPE_NORO); /* no error */ + uptr->fileref = sim_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 = sim_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 = sim_fread (uptr->filebuf, SZ_D (dptr), /* read file */ - cap, uptr->fileref); - uptr->flags = uptr->flags | UNIT_BUF; } /* set buffered */ + uptr->hwmark = sim_fread (uptr->filebuf, /* read file */ + SZ_D (dptr), cap, uptr->fileref); + uptr->flags = uptr->flags | UNIT_BUF; /* set buffered */ + } uptr->flags = uptr->flags | UNIT_ATT; uptr->pos = 0; return SCPE_OK; @@ -1641,11 +1750,11 @@ free (uptr->filename); uptr->filename = NULL; return stat; } - + /* Detach command - det[ach] all detach all units - det[ach] unit detach specified unit + det[ach] all detach all units + det[ach] unit detach specified unit */ t_stat detach_cmd (int32 flag, char *cptr) @@ -1654,24 +1763,24 @@ 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? */ +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? */ -return scp_detach_unit (dptr, uptr); /* detach */ +dptr = find_unit (gbuf, &uptr); /* locate unit */ +if (dptr == NULL) return SCPE_NXDEV; /* found dev? */ +if (uptr == NULL) return SCPE_NXUN; /* valid unit? */ +return scp_detach_unit (dptr, uptr); /* detach */ } /* Detach devices start..end Inputs: - start = number of starting device - shutdown = TRUE if simulator shutting down + start = number of starting device + shutdown = TRUE if simulator shutting down Outputs: - status = error status + status = error status Note that during shutdown, detach routines for non-attachable devices will be called. These routines can implement simulator shutdown. @@ -1685,14 +1794,17 @@ UNIT *uptr; t_stat r; if ((start < 0) || (start > 1)) return SCPE_IERR; -for (i = start; (dptr = sim_devices[i]) != NULL; i++) { /* loop thru dev */ - for (j = 0; j < dptr->numunits; j++) { /* loop thru units */ - uptr = (dptr->units) + j; - if ((uptr->flags & UNIT_ATT) || /* attached? */ - (shutdown && dptr->detach && /* shutdown, spec rtn, */ - !(uptr->flags & UNIT_ATTABLE))) { /* !attachable? */ - r = scp_detach_unit (dptr, uptr); /* detach unit */ - if (r != SCPE_OK) return r; } } } +for (i = start; (dptr = sim_devices[i]) != NULL; i++) { /* loop thru dev */ + for (j = 0; j < dptr->numunits; j++) { /* loop thru units */ + uptr = (dptr->units) + j; + if ((uptr->flags & UNIT_ATT) || /* attached? */ + (shutdown && dptr->detach && /* shutdown, spec rtn, */ + !(uptr->flags & UNIT_ATTABLE))) { /* !attachable? */ + r = scp_detach_unit (dptr, uptr); /* detach unit */ + if (r != SCPE_OK) return r; + } + } + } return SCPE_OK; } @@ -1700,8 +1812,8 @@ return SCPE_OK; t_stat scp_detach_unit (DEVICE *dptr, UNIT *uptr) { -if (dptr->detach != NULL) return dptr->detach (uptr); /* device routine? */ -return detach_unit (uptr); /* no, standard */ +if (dptr->detach != NULL) return dptr->detach (uptr); /* device routine? */ +return detach_unit (uptr); /* no, standard */ } /* Detach unit from file */ @@ -1711,30 +1823,33 @@ t_stat detach_unit (UNIT *uptr) DEVICE *dptr; if (uptr == NULL) return SCPE_IERR; -if (!(uptr->flags & UNIT_ATTABLE)) return SCPE_NOATT; /* attachable? */ -if (!(uptr->flags & UNIT_ATT)) return SCPE_OK; /* attached? */ +if (!(uptr->flags & UNIT_ATTABLE)) return SCPE_NOATT; /* attachable? */ +if (!(uptr->flags & UNIT_ATT)) return SCPE_OK; /* attached? */ 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); - sim_fwrite (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; } + 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); + sim_fwrite (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; if (fclose (uptr->fileref) == EOF) return SCPE_IOERR; return SCPE_OK; } - + /* Assign command - as[sign] device name assign logical name to device + as[sign] device name assign logical name to device */ t_stat assign_cmd (int32 flag, char *cptr) @@ -1742,23 +1857,23 @@ 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 */ +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)); +dptr->lname = (char *) calloc (CBUFSIZE, sizeof (char)); if (dptr->lname == NULL) return SCPE_MEM; strncpy (dptr->lname, cptr, CBUFSIZE); return SCPE_OK; @@ -1766,7 +1881,7 @@ return SCPE_OK; /* Deassign command - dea[ssign] device deassign logical name + dea[ssign] device deassign logical name */ t_stat deassign_cmd (int32 flag, char *cptr) @@ -1774,12 +1889,12 @@ 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? */ +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); } @@ -1796,18 +1911,19 @@ char *sim_dname (DEVICE *dptr) { return (dptr->lname? dptr->lname: dptr->name); } - + /* Save command - sa[ve] filename save state to specified file + 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 */ +GET_SWITCHES (cptr); /* get switches */ +if (*cptr == 0) return SCPE_2FARG; /* must be more */ +sim_trim_endspc (cptr); if ((sfile = sim_fopen (cptr, "wb")) == NULL) return SCPE_OPENERR; r = sim_save (sfile); fclose (sfile); @@ -1830,80 +1946,86 @@ REG *rptr; #define WRITE_I(xx) sim_fwrite (&(xx), sizeof (xx), 1, sfile) -fputs (save_vercur, sfile); /* [V2.5] save format */ +fputs (save_vercur, sfile); /* [V2.5] save format */ fputc ('\n', sfile); -fputs (sim_name, sfile); /* sim name */ +fputs (sim_name, sfile); /* sim name */ fputc ('\n', sfile); -fprintf (sfile, "%.0f\n", sim_time); /* [V3.2] sim time */ -WRITE_I (sim_rtime); /* [V2.6] sim rel time */ +fprintf (sfile, "%.0f\n", sim_time); /* [V3.2] 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, SIM_SW_REST); - 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 */ - sim_fwrite (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? */ +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, SIM_SW_REST); + 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 */ + sim_fwrite (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 + re[store] filename restore state from specified file */ t_stat restore_cmd (int32 flag, char *cptr) @@ -1911,8 +2033,9 @@ 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 */ +GET_SWITCHES (cptr); /* get switches */ +if (*cptr == 0) return SCPE_2FARG; /* must be more */ +sim_trim_endspc (cptr); if ((rfile = sim_fopen (cptr, "rb")) == NULL) return SCPE_OPENERR; r = sim_rest (rfile); fclose (rfile); @@ -1935,141 +2058,157 @@ UNIT *uptr; REG *rptr; #define READ_S(xx) if (read_line ((xx), CBUFSIZE, rfile) == NULL) \ - return SCPE_IOERR; + return SCPE_IOERR; #define READ_I(xx) if (sim_fread (&xx, sizeof (xx), 1, rfile) == 0) \ - return SCPE_IOERR; + return SCPE_IOERR; -READ_S (buf); /* [V2.5+] read version */ -if (strcmp (buf, save_vercur) == 0) v32 = v30 = TRUE; /* version 3.2? */ -else if (strcmp (buf, save_ver30) == 0) v30 = TRUE; /* version 3.0? */ -else if (strcmp (buf, save_ver210) != 0) { /* version 2.10? */ - 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; } -if (v32) { /* [V3.2] time as string */ - READ_S (buf); - sscanf (buf, "%lf", &sim_time); } -else READ_I (sim_time); /* sim time */ -READ_I (sim_rtime); /* [V2.6+] sim rel time */ +READ_S (buf); /* [V2.5+] read version */ +if (strcmp (buf, save_vercur) == 0) v32 = v30 = TRUE; /* version 3.2? */ +else if (strcmp (buf, save_ver30) == 0) v30 = TRUE; /* version 3.0? */ +else if (strcmp (buf, save_ver210) != 0) { /* version 2.10? */ + 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; + } +if (v32) { /* [V3.2] time as string */ + READ_S (buf); + sscanf (buf, "%lf", &sim_time); + } +else 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; } - READ_I (flg); /* [V2.10+] ctlr flags */ - if (!v32) flg = ((flg & DEV_UFMASK_31) << (DEV_V_UF - DEV_V_UF_31)) | - (flg & ~DEV_UFMASK_31); /* [V3.2] flags moved */ - dptr->flags = (dptr->flags & ~DEV_RFLAGS) | /* restore ctlr flags */ - (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); } - READ_I (flg); /* [V2.10+] unit flags */ - if (!v32) flg = ((flg & UNIT_UFMASK_31) << (UNIT_V_UF - UNIT_V_UF_31)) | - (flg & ~UNIT_UFMASK_31); /* [V3.2] flags moved */ - uptr->flags = (uptr->flags & ~UNIT_RFLAGS) | - (flg & UNIT_RFLAGS); /* restore */ - READ_S (buf); /* attached file */ - if ((uptr->flags & UNIT_ATTABLE) && /* if attachable and */ - (!(dptr->flags & DEV_NET) || /* not net dev or */ - !(uptr->flags & UNIT_ATT) || /* not currently att */ - (buf[0] == 0))) { /* or will not be att */ - sim_switches = SIM_SW_REST; /* att-det/rest */ - r = scp_detach_unit (dptr, uptr); /* detach old */ - if (r != SCPE_OK) return r; - if (buf[0] != 0) { /* any file? */ - uptr->flags = uptr->flags & ~UNIT_DIS; - if (flg & UNIT_RO) /* [V2.10+] saved flgs & RO? */ - sim_switches |= SWMASK ('R'); /* RO attach */ - r = scp_attach_unit (dptr, 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 = sim_fread (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, SIM_SW_REST); - 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? */ - 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); - for (us = 0; us < depth; us++) { /* skip values */ - READ_I (val); } - continue; } - if (depth != rptr->depth) /* [V2.10+] mismatch? */ - printf ("Register depth mismatch: %s %s, file = %d, sim = %d\n", - sim_dname (dptr), buf, depth, rptr->depth); - 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 */ +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; + } + READ_I (flg); /* [V2.10+] ctlr flags */ + if (!v32) flg = ((flg & DEV_UFMASK_31) << (DEV_V_UF - DEV_V_UF_31)) | + (flg & ~DEV_UFMASK_31); /* [V3.2] flags moved */ + dptr->flags = (dptr->flags & ~DEV_RFLAGS) | /* restore ctlr flags */ + (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); + } + READ_I (flg); /* [V2.10+] unit flags */ + if (!v32) flg = ((flg & UNIT_UFMASK_31) << (UNIT_V_UF - UNIT_V_UF_31)) | + (flg & ~UNIT_UFMASK_31); /* [V3.2] flags moved */ + uptr->flags = (uptr->flags & ~UNIT_RFLAGS) | + (flg & UNIT_RFLAGS); /* restore */ + READ_S (buf); /* attached file */ + if ((uptr->flags & UNIT_ATTABLE) && /* if attachable and */ + (!(dptr->flags & DEV_NET) || /* not net dev or */ + !(uptr->flags & UNIT_ATT) || /* not currently att */ + (buf[0] == 0))) { /* or will not be att */ + sim_switches = SIM_SW_REST; /* att-det/rest */ + r = scp_detach_unit (dptr, uptr); /* detach old */ + if (r != SCPE_OK) return r; + if (buf[0] != 0) { /* any file? */ + uptr->flags = uptr->flags & ~UNIT_DIS; + if (flg & UNIT_RO) /* [V2.10+] saved flgs & RO? */ + sim_switches |= SWMASK ('R'); /* RO attach */ + r = scp_attach_unit (dptr, 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 = sim_fread (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, SIM_SW_REST); + 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? */ + 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); + for (us = 0; us < depth; us++) { /* skip values */ + READ_I (val); + } + continue; + } + if (depth != rptr->depth) /* [V2.10+] mismatch? */ + printf ("Register depth mismatch: %s %s, file = %d, sim = %d\n", + sim_dname (dptr), buf, depth, rptr->depth); + 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; } - + /* 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 + 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) @@ -2083,118 +2222,136 @@ DEVICE *dptr; UNIT *uptr; void int_handler (int signal); -GET_SWITCHES (cptr); /* get switches */ +GET_SWITCHES (cptr); /* get switches */ sim_step = 0; -if (((flag == RU_RUN) || (flag == RU_GO)) && (*cptr != 0)) { /* run or go */ - cptr = get_glyph (cptr, gbuf, 0); /* get next glyph */ - if (sim_vm_parse_addr) /* address parser? */ - pcv = sim_vm_parse_addr (sim_devices[0], gbuf, &tptr); - else pcv = strtotv (gbuf, &tptr, sim_PC->radix); - if ((tptr == gbuf) || (*tptr != 0) || - (pcv > width_mask[sim_PC->width])) return SCPE_ARG; - put_rval (sim_PC, 0, pcv); } +if (((flag == RU_RUN) || (flag == RU_GO)) && (*cptr != 0)) { /* run or go */ + cptr = get_glyph (cptr, gbuf, 0); /* get next glyph */ + if (sim_vm_parse_addr) /* address parser? */ + pcv = sim_vm_parse_addr (sim_dflt_dev, gbuf, &tptr); + else pcv = strtotv (gbuf, &tptr, sim_PC->radix); + if ((tptr == gbuf) || (*tptr != 0) || + (pcv > width_mask[sim_PC->width])) return SCPE_ARG; + put_rval (sim_PC, 0, pcv); + } -if (flag == RU_STEP) { /* step */ - if (*cptr == 0) sim_step = 1; - else { - cptr = get_glyph (cptr, gbuf, 0); - sim_step = (int32) get_uint (gbuf, 10, INT_MAX, &r); - if ((r != SCPE_OK) || (sim_step <= 0)) return SCPE_ARG; } } +if (flag == RU_STEP) { /* step */ + if (*cptr == 0) sim_step = 1; + else { + cptr = get_glyph (cptr, gbuf, 0); + sim_step = (int32) get_uint (gbuf, 10, INT_MAX, &r); + if ((r != SCPE_OK) || (sim_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 (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 = (int32) (uptr - dptr->units); /* recover unit# */ + if ((r = dptr->boot (unitno, dptr)) != SCPE_OK) return r; + } -if (*cptr != 0) return SCPE_2MARG; /* now eol? */ +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_p (0)) != SCPE_OK) return r; } +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_p (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)) - sim_fseek (uptr->fileref, uptr->pos, SEEK_SET); } } + for (j = 0; j < dptr->numunits; j++) { + uptr = dptr->units + j; + if ((uptr->flags & (UNIT_ATT + UNIT_SEQ)) == + (UNIT_ATT + UNIT_SEQ)) + sim_fseek (uptr->fileref, uptr->pos, SEEK_SET); + } + } stop_cpu = 0; -if (signal (SIGINT, int_handler) == SIG_ERR) { /* set WRU */ - return SCPE_SIGERR; } -if (sim_ttrun () != SCPE_OK) { /* set console mode */ - sim_ttcmd (); - return SCPE_TTYERR; } -if ((r = sim_check_console (30)) != SCPE_OK) { /* check console, error? */ - sim_ttcmd (); - return r; } -if (sim_step) sim_activate (&sim_step_unit, sim_step); /* set step timer */ -sim_is_running = 1; /* flag running */ -sim_brk_clract (); /* defang actions */ +if (signal (SIGINT, int_handler) == SIG_ERR) { /* set WRU */ + return SCPE_SIGERR; + } +if (sim_ttrun () != SCPE_OK) { /* set console mode */ + sim_ttcmd (); + return SCPE_TTYERR; + } +if ((r = sim_check_console (30)) != SCPE_OK) { /* check console, error? */ + sim_ttcmd (); + return r; + } +if (sim_step) sim_activate (&sim_step_unit, sim_step); /* set step timer */ +sim_is_running = 1; /* flag running */ +sim_brk_clract (); /* defang actions */ r = sim_instr(); -sim_is_running = 0; /* flag idle */ -sim_ttcmd (); /* restore console */ -signal (SIGINT, SIG_DFL); /* cancel WRU */ -sim_cancel (&sim_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 (sim_log) fflush (sim_log); /* flush console log */ -if (sim_deb) fflush (sim_deb); /* flush debug log */ -for (i = 1; (dptr = sim_devices[i]) != NULL; i++) { /* flush attached files */ - for (j = 0; j < dptr->numunits; j++) { /* if not buffered in mem */ - uptr = dptr->units + j; - if ((uptr->flags & UNIT_ATT) && /* attached, */ - !(uptr->flags & UNIT_BUF) && /* not buffered, */ - (uptr->fileref) && /* real file, */ - !(uptr->flags & UNIT_RAW) && /* not raw, */ - !(uptr->flags & UNIT_RO)) /* not read only? */ - fflush (uptr->fileref); } } +sim_is_running = 0; /* flag idle */ +sim_ttcmd (); /* restore console */ +signal (SIGINT, SIG_DFL); /* cancel WRU */ +sim_cancel (&sim_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 (sim_log) fflush (sim_log); /* flush console log */ +if (sim_deb) fflush (sim_deb); /* flush debug log */ +for (i = 1; (dptr = sim_devices[i]) != NULL; i++) { /* flush attached files */ + for (j = 0; j < dptr->numunits; j++) { /* if not buffered in mem */ + uptr = dptr->units + j; + if ((uptr->flags & UNIT_ATT) && /* attached, */ + !(uptr->flags & UNIT_BUF) && /* not buffered, */ + (uptr->fileref) && /* real file, */ + !(uptr->flags & UNIT_RAW) && /* not raw, */ + !(uptr->flags & UNIT_RO)) /* not read only? */ + fflush (uptr->fileref); + } + } #if defined (VMS) printf ("\n"); #endif -fprint_stopped (stdout, r); /* print msg */ -if (sim_log) fprint_stopped (sim_log, r); /* log if enabled */ +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 *st, t_stat v) { int32 i; -t_stat r; +t_stat r = 0; t_addr k; t_value pcval; DEVICE *dptr; if (v >= SCPE_BASE) fprintf (st, "\n%s, %s: ", - scp_error_messages[v - SCPE_BASE], sim_PC->name); + scp_error_messages[v - SCPE_BASE], sim_PC->name); else fprintf (st, "\n%s, %s: ", sim_stop_messages[v], sim_PC->name); pcval = get_rval (sim_PC, 0); -if (sim_vm_fprint_addr) sim_vm_fprint_addr (st, sim_devices[0], (t_addr) pcval); +if (sim_vm_fprint_addr) sim_vm_fprint_addr (st, sim_dflt_dev, (t_addr) pcval); else fprint_val (st, pcval, sim_PC->radix, sim_PC->width, - sim_PC->flags & REG_FMT); -if (((dptr = sim_devices[0]) != NULL) && (dptr->examine != NULL)) { + sim_PC->flags & REG_FMT); +if (((dptr = sim_dflt_dev) != 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 = dptr->examine (&sim_eval[i], k, dptr->units, + SWMASK ('V'))) != SCPE_OK) break; + } if ((r == SCPE_OK) || (i > 0)) { - fprintf (st, " ("); - if (fprint_sym (st, (t_addr) pcval, sim_eval, NULL, SWMASK('M')|SIM_SW_STOP) > 0) - fprint_val (st, sim_eval[0], dptr->dradix, dptr->dwidth, PV_RZRO); - fprintf (st, ")"); } } + fprintf (st, " ("); + if (fprint_sym (st, (t_addr) pcval, sim_eval, NULL, SWMASK('M')|SIM_SW_STOP) > 0) + fprint_val (st, sim_eval[0], dptr->dradix, dptr->dwidth, PV_RZRO); + fprintf (st, ")"); + } + } fprintf (st, "\n"); return; } @@ -2221,25 +2378,25 @@ 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 + 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 + @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 + 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) @@ -2252,67 +2409,72 @@ DEVICE *tdptr; REG *lowr, *highr; FILE *ofile; -opt = CMD_OPT_SW|CMD_OPT_SCH|CMD_OPT_DFT; /* options for all */ -if (flag == EX_E) opt = opt | CMD_OPT_OF; /* extra for EX */ -cptr = get_sim_opt (opt, cptr, &reason); /* get cmd options */ -if (!cptr) return reason; /* error? */ -if (*cptr == 0) return SCPE_2FARG; /* must be more */ -if (sim_dfunit == NULL) return SCPE_NXUN; /* got a unit? */ -cptr = get_glyph (cptr, gbuf, 0); /* get list */ -if ((flag == EX_D) && (*cptr == 0)) return SCPE_2FARG; /* deposit needs more */ -ofile = sim_ofile? sim_ofile: stdout; /* no ofile? use stdout */ +opt = CMD_OPT_SW|CMD_OPT_SCH|CMD_OPT_DFT; /* options for all */ +if (flag == EX_E) opt = opt | CMD_OPT_OF; /* extra for EX */ +cptr = get_sim_opt (opt, cptr, &reason); /* get cmd options */ +if (!cptr) return reason; /* error? */ +if (*cptr == 0) return SCPE_2FARG; /* must be more */ +if (sim_dfunit == NULL) return SCPE_NXUN; /* got a unit? */ +cptr = get_glyph (cptr, gbuf, 0); /* get list */ +if ((flag == EX_D) && (*cptr == 0)) return SCPE_2FARG; /* deposit needs more */ +ofile = sim_ofile? sim_ofile: stdout; /* no ofile? use stdout */ for (gptr = gbuf, reason = SCPE_OK; - (*gptr != 0) && (reason == SCPE_OK); gptr = tptr) { - tdptr = sim_dfdev; /* working dptr */ - if (strncmp (gptr, "STATE", strlen ("STATE")) == 0) { - tptr = gptr + strlen ("STATE"); - if (*tptr && (*tptr++ != ',')) return SCPE_ARG; - if ((lowr = sim_dfdev->registers) == NULL) return SCPE_NXREG; - for (highr = lowr; highr->name != NULL; highr++) ; - sim_switches = sim_switches | SIM_SW_HIDE; - reason = exdep_reg_loop (ofile, sim_schptr, flag, cptr, - lowr, --highr, 0, 0); - continue; } + (*gptr != 0) && (reason == SCPE_OK); gptr = tptr) { + tdptr = sim_dfdev; /* working dptr */ + if (strncmp (gptr, "STATE", strlen ("STATE")) == 0) { + tptr = gptr + strlen ("STATE"); + if (*tptr && (*tptr++ != ',')) return SCPE_ARG; + if ((lowr = sim_dfdev->registers) == NULL) return SCPE_NXREG; + for (highr = lowr; highr->name != NULL; highr++) ; + sim_switches = sim_switches | SIM_SW_HIDE; + reason = exdep_reg_loop (ofile, sim_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 (NULL, 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, sim_schptr, flag, cptr, - lowr, highr, (uint32) low, (uint32) high); - 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 (NULL, 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, sim_schptr, flag, cptr, + lowr, highr, (uint32) low, (uint32) high); + continue; + } - tptr = get_range (sim_dfdev, gptr, &low, &high, sim_dfdev->aradix, - (((sim_dfunit->capac == 0) || (flag == EX_E))? 0: - sim_dfunit->capac - sim_dfdev->aincr), 0); - if (tptr == NULL) return SCPE_ARG; - if (*tptr && (*tptr++ != ',')) return SCPE_ARG; - reason = exdep_addr_loop (ofile, sim_schptr, flag, cptr, low, high, - sim_dfdev, sim_dfunit); - } /* end for */ -if (sim_ofile) fclose (sim_ofile); /* close output file */ + tptr = get_range (sim_dfdev, gptr, &low, &high, sim_dfdev->aradix, + (((sim_dfunit->capac == 0) || (flag == EX_E))? 0: + sim_dfunit->capac - sim_dfdev->aincr), 0); + if (tptr == NULL) return SCPE_ARG; + if (*tptr && (*tptr++ != ',')) return SCPE_ARG; + reason = exdep_addr_loop (ofile, sim_schptr, flag, cptr, low, high, + sim_dfdev, sim_dfunit); + } /* end for */ +if (sim_ofile) fclose (sim_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 + 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) + REG *lowr, REG *highr, uint32 lows, uint32 highs) { t_stat reason; uint32 idx; @@ -2322,65 +2484,69 @@ 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; } } } + 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 low, t_addr high, DEVICE *dptr, UNIT *uptr) { t_addr i, mask; t_stat reason; -if (uptr->flags & UNIT_DIS) return SCPE_UDIS; /* disabled? */ +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; ) { /* all paths must incr!! */ - 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)) - i = i + dptr->aincr; /* sch fails, incr */ - else { /* no sch or success */ - if (flag != EX_D) { /* ex, ie, or id? */ - 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); - } - else reason = 1 - dptr->aincr; /* no, dflt incr */ - if (flag != EX_E) { /* ie, id, or d? */ - reason = dep_addr (flag, cptr, i, dptr, uptr, reason); - if (reason > SCPE_OK) return reason; - } - i = i + (1 - reason); /* incr */ - } - } +for (i = low; i <= high; ) { /* all paths must incr!! */ + 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)) + i = i + dptr->aincr; /* sch fails, incr */ + else { /* no sch or success */ + if (flag != EX_D) { /* ex, ie, or id? */ + 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); + } + else reason = 1 - dptr->aincr; /* no, dflt incr */ + if (flag != EX_E) { /* ie, id, or d? */ + reason = dep_addr (flag, cptr, i, dptr, uptr, reason); + if (reason > SCPE_OK) return reason; + } + i = i + (1 - reason); /* incr */ + } + } 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 + 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 + return = error status */ t_stat ex_reg (FILE *ofile, t_value val, int32 flag, REG *rptr, uint32 idx) @@ -2388,16 +2554,16 @@ 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 (rptr->depth > 1) fprintf (ofile, "%s[%d]:\t", rptr->name, idx); +else fprintf (ofile, "%s:\t", rptr->name); if (!(flag & EX_E)) return SCPE_OK; GET_RADIX (rdx, rptr->radix); if ((rptr->flags & REG_VMAD) && sim_vm_fprint_addr) - sim_vm_fprint_addr (ofile, sim_devices[0], (t_addr) val); + sim_vm_fprint_addr (ofile, sim_dflt_dev, (t_addr) val); else if (!(rptr->flags & REG_VMIO) || (fprint_sym (ofile, rdx, &val, NULL, sim_switches | SIM_SW_REG) > 0)) - fprint_val (ofile, val, rdx, rptr->width, rptr->flags & REG_FMT); -if (flag & EX_I) fprintf (ofile, " "); + fprint_val (ofile, val, rdx, rptr->width, rptr->flags & REG_FMT); +if (flag & EX_I) fprintf (ofile, "\t"); else fprintf (ofile, "\n"); return SCPE_OK; } @@ -2405,10 +2571,10 @@ return SCPE_OK; /* Get register value Inputs: - rptr = pointer to register descriptor - idx = index + rptr = pointer to register descriptor + idx = index Outputs: - return = register value + return = register value */ t_value get_rval (REG *rptr, uint32 idx) @@ -2419,23 +2585,25 @@ 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; } + 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; + uptr = ((UNIT *) rptr->loc) + idx; #if defined (USE_INT64) - if (sz <= sizeof (uint32)) val = *((uint32 *) uptr); - else val = *((t_uint64 *) uptr); } + if (sz <= sizeof (uint32)) val = *((uint32 *) uptr); + else val = *((t_uint64 *) uptr); #else - val = *((uint32 *) uptr); } + val = *((uint32 *) uptr); #endif + } else if ((rptr->depth > 1) && (sz == sizeof (uint8))) - val = *(((uint8 *) rptr->loc) + idx); + val = *(((uint8 *) rptr->loc) + idx); else if ((rptr->depth > 1) && (sz == sizeof (uint16))) - val = *(((uint16 *) rptr->loc) + idx); + val = *(((uint16 *) rptr->loc) + idx); #if defined (USE_INT64) else if (sz <= sizeof (uint32)) - val = *(((uint32 *) rptr->loc) + idx); + val = *(((uint32 *) rptr->loc) + idx); else val = *(((t_uint64 *) rptr->loc) + idx); #else else val = *(((uint32 *) rptr->loc) + idx); @@ -2443,16 +2611,16 @@ else val = *(((uint32 *) rptr->loc) + idx); 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 + flag = type of deposit (normal/interactive) + cptr = pointer to input string + rptr = pointer to register descriptor + idx = index Outputs: - return = error status + return = error status */ t_stat dep_reg (int32 flag, char *cptr, REG *rptr, uint32 idx) @@ -2465,20 +2633,23 @@ char *tptr, 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 */ + 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_VMAD) && sim_vm_parse_addr) { /* address form? */ - val = sim_vm_parse_addr (sim_devices[0], cptr, &tptr); - if ((tptr == cptr) || (*tptr != 0) || - (val > mask)) return SCPE_ARG; } -else if (!(rptr->flags & REG_VMIO) || /* dont use sym? */ +if ((rptr->flags & REG_VMAD) && sim_vm_parse_addr) { /* address form? */ + val = sim_vm_parse_addr (sim_dflt_dev, cptr, &tptr); + if ((tptr == cptr) || (*tptr != 0) || + (val > mask)) return SCPE_ARG; + } +else if (!(rptr->flags & REG_VMIO) || /* dont use sym? */ (parse_sym (cptr, rdx, NULL, &val, sim_switches | SIM_SW_REG) > SCPE_OK)) { - val = get_uint (cptr, rdx, mask, &r); - if (r != SCPE_OK) return SCPE_ARG; } + 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; @@ -2487,12 +2658,12 @@ return SCPE_OK; /* Put register value Inputs: - rptr = pointer to register descriptor - idx = index - val = new value - mask = mask + rptr = pointer to register descriptor + idx = index + val = new value + mask = mask Outputs: - none + none */ void put_rval (REG *rptr, uint32 idx, t_value val) @@ -2502,55 +2673,57 @@ 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) + *(((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; } + 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; + uptr = ((UNIT *) rptr->loc) + idx; #if defined (USE_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); } + 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); } + *((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); + 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); + PUT_RVAL (uint16, rptr, idx, (uint32) val, (uint32) mask); #if defined (USE_INT64) else if (sz <= sizeof (uint32)) - PUT_RVAL (uint32, rptr, idx, (int32) val, (uint32) mask); + 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 + 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 addr units retired + return = if > 0, error status + if <= 0,-number of extra addr units retired */ t_stat ex_addr (FILE *ofile, int32 flag, t_addr addr, DEVICE *dptr, UNIT *uptr) @@ -2560,15 +2733,15 @@ int32 rdx; if (sim_vm_fprint_addr) sim_vm_fprint_addr (ofile, dptr, addr); else fprint_val (ofile, addr, dptr->aradix, dptr->awidth, PV_LEFT); -fprintf (ofile, ": "); +fprintf (ofile, ":\t"); if (!(flag & EX_E)) return (1 - dptr->aincr); GET_RADIX (rdx, dptr->dradix); if ((reason = fprint_sym (ofile, addr, sim_eval, uptr, sim_switches)) > 0) { - fprint_val (ofile, sim_eval[0], rdx, dptr->dwidth, PV_RZRO); - reason = 1 - dptr->aincr; - } -if (flag & EX_I) fprintf (ofile, " "); + fprint_val (ofile, sim_eval[0], rdx, dptr->dwidth, PV_RZRO); + reason = 1 - dptr->aincr; + } +if (flag & EX_I) fprintf (ofile, "\t"); else fprintf (ofile, "\n"); return reason; } @@ -2576,12 +2749,12 @@ 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 + 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 + return = error status */ t_stat get_aval (t_addr addr, DEVICE *dptr, UNIT *uptr) @@ -2596,51 +2769,59 @@ 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_RAW) return SCPE_NOFNC; - 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 { - sim_fseek (uptr->fileref, sz * loc, SEEK_SET); - sim_fread (&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 (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_RAW) return SCPE_NOFNC; + 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 { + sim_fseek (uptr->fileref, sz * loc, SEEK_SET); + sim_fread (&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 + 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 address units retired + return = if > 0, error status + if <= 0, -number of extra address units retired */ t_stat dep_addr (int32 flag, char *cptr, t_addr addr, DEVICE *dptr, - UNIT *uptr, int32 dfltinc) + UNIT *uptr, int32 dfltinc) { int32 i, count, rdx; t_addr j, loc; @@ -2651,48 +2832,56 @@ 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? */ + 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; } + sim_eval[0] = get_uint (cptr, rdx, mask, &reason); + if (reason != SCPE_OK) return reason; + } count = (1 - reason + (dptr->aincr - 1)) / dptr->aincr; 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_RAW) return SCPE_NOFNC; - 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 { - sim_fseek (uptr->fileref, sz * loc, SEEK_SET); - sim_fwrite (&sim_eval[i], sz, 1, uptr->fileref); - if (ferror (uptr->fileref)) { - clearerr (uptr->fileref); - return SCPE_IOERR; } } } } + 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_RAW) return SCPE_NOFNC; + 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 { + sim_fseek (uptr->fileref, sz * loc, SEEK_SET); + sim_fwrite (&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]; +DEVICE *dptr = sim_dflt_dev; int32 i, rdx, a, lim; t_stat r; @@ -2701,76 +2890,104 @@ 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; } + sim_eval[0] = get_uint (cptr, rdx, width_mask[dptr->dwidth], &r); + if (r != SCPE_OK) return r; + } lim = 1 - r; for (i = a = 0; a < lim; ) { - printf ("%d:\t", a); - if ((r = fprint_sym (stdout, a, &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, a, &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) a = a + 1 - r; - else a = a + dptr->aincr; - i = a / dptr->aincr; - } + printf ("%d:\t", a); + if ((r = fprint_sym (stdout, a, &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, a, &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) a = a + 1 - r; + else a = a + dptr->aincr; + i = a / dptr->aincr; + } return SCPE_OK; } - + /* String processing routines - read_line read line + read_line read line Inputs: - cptr = pointer to buffer - size = maximum size - stream = pointer to input stream + cptr = pointer to buffer + size = maximum size + stream = pointer to input stream Outputs: - optr = pointer to first non-blank character - NULL if EOF + 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 !defined (HAVE_READLINE) +cptr = fgets (cptr, size, stream); /* get cmd line */ + +#else +if (stream != stdin) cptr = fgets (cptr, size, stream); +else { + char *tmpc = readline (NULL); + if (tmpc == NULL) cptr = NULL; + else { + strncpy (cptr, tmpc, size); + free (tmpc); + } + } +#endif + 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 */ + 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 == (cptr + size - 1))) { /* str max length? */ + *tptr = 0; /* terminate */ + break; + } + } +while (isspace (*cptr)) cptr++; /* trim leading spc */ +if (*cptr == ';') *cptr = 0; /* ignore comment */ + +#if defined (HAVE_READLINE) +add_history (cptr); + +#endif 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) +/* 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) + 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 + 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++; } + 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 */ +if (mchar && (*iptr == mchar)) iptr++; /* skip terminator */ +while (isspace (*iptr)) iptr++; /* absorb spaces */ return iptr; } @@ -2783,14 +3000,31 @@ char *get_glyph_nc (char *iptr, char *optr, char mchar) { return get_glyph_gen (iptr, optr, mchar, FALSE); } - -/* get_yn yes/no question + +/* Trim trailing spaces from a string + + Inputs: + cptr = pointer to string + Outputs: + cptr = pointer to string +*/ + +char *sim_trim_endspc (char *cptr) +{ +char *tptr; + +tptr = cptr + strlen (cptr); +while ((--tptr >= cptr) && isspace (*tptr)) *tptr = 0; +return cptr; +} + +/* get_yn yes/no question Inputs: - cptr = pointer to question - deflt = default answer + cptr = pointer to question + deflt = default answer Outputs: - result = true if yes, false if no + result = true if yes, false if no */ t_stat get_yn (char *ques, t_stat deflt) @@ -2804,15 +3038,15 @@ if ((*cptr == 'Y') || (*cptr == 'y')) return TRUE; return FALSE; } -/* get_uint unsigned number +/* get_uint unsigned number Inputs: - cptr = pointer to input string - radix = input radix - max = maximum acceptable value - *status = pointer to error status + cptr = pointer to input string + radix = input radix + max = maximum acceptable value + *status = pointer to error status Outputs: - val = value + val = value */ t_value get_uint (char *cptr, uint32 radix, t_value max, t_stat *status) @@ -2823,64 +3057,71 @@ 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; } +else { + while (isspace (*tptr)) tptr++; + if (*tptr != 0) *status = SCPE_ARG; + } return val; } -/* get_range range specification +/* get_range range specification Inputs: - dptr = pointer to device (NULL if none) - cptr = pointer to input string - *lo = pointer to low result - *hi = pointer to high result - aradix = radix - max = default high value - term = terminating character, 0 if none + dptr = pointer to device (NULL if none) + cptr = pointer to input string + *lo = pointer to low result + *hi = pointer to high result + aradix = radix + max = default high value + term = terminating character, 0 if none Outputs: - tptr = input pointer after processing - NULL if error + tptr = input pointer after processing + NULL if error */ char *get_range (DEVICE *dptr, char *cptr, t_addr *lo, t_addr *hi, - uint32 rdx, t_addr max, char term) + 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 { if (dptr && sim_vm_parse_addr) /* get low */ - *lo = sim_vm_parse_addr (dptr, cptr, &tptr); - else *lo = (t_addr) strtotv (cptr, &tptr, rdx); - if (cptr == tptr) return NULL; /* error? */ - if ((*tptr == '-') || (*tptr == ':')) { /* range? */ - cptr = tptr + 1; - if (dptr && sim_vm_parse_addr) /* get high */ - *hi = sim_vm_parse_addr (dptr, cptr, &tptr); - else *hi = (t_addr) strtotv (cptr, &tptr, rdx); - 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; } + tptr = cptr + strlen ("ALL"); + *lo = 0; + *hi = max; + } +else { + if (dptr && sim_vm_parse_addr) /* get low */ + *lo = sim_vm_parse_addr (dptr, cptr, &tptr); + else *lo = (t_addr) strtotv (cptr, &tptr, rdx); + if (cptr == tptr) return NULL; /* error? */ + if ((*tptr == '-') || (*tptr == ':')) { /* range? */ + cptr = tptr + 1; + if (dptr && sim_vm_parse_addr) /* get high */ + *hi = sim_vm_parse_addr (dptr, cptr, &tptr); + else *hi = (t_addr) strtotv (cptr, &tptr, rdx); + 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 +/* get_ipaddr IP address:port Inputs: - cptr = pointer to input string + 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 + 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) @@ -2891,40 +3132,45 @@ uint32 i, addr, port, octet; t_stat r; if ((cptr == NULL) || (*cptr == 0) || (ipa == NULL) || (ipp == NULL)) - return SCPE_ARG; + 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; } +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; } + 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 + +/* Find_device find device matching input string Inputs: - cptr = pointer to input string + cptr = pointer to input string Outputs: - result = pointer to device + result = pointer to device */ DEVICE *find_dev (char *cptr) @@ -2933,20 +3179,21 @@ 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; } + if ((strcmp (cptr, dptr->name) == 0) || + (dptr->lname && + (strcmp (cptr, dptr->lname) == 0))) return dptr; + } return NULL; } -/* Find_unit find unit matching input string +/* Find_unit find unit matching input string Inputs: - cptr = pointer to input string - uptr = pointer to unit pointer + 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) + result = pointer to device (null if no dev) + *iptr = pointer to unit (null if nx unit) */ DEVICE *find_unit (char *cptr, UNIT **uptr) @@ -2956,34 +3203,38 @@ 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; } +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; } } } +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 +/* Find_dev_from_unit find device for unit Inputs: - uptr = pointer to unit + uptr = pointer to unit Outputs: - result = pointer to device + result = pointer to device */ DEVICE *find_dev_from_unit (UNIT *uptr) @@ -2993,8 +3244,10 @@ 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; } } + for (j = 0; j < dptr->numunits; j++) { + if (uptr == (dptr->units + j)) return dptr; + } + } return NULL; } @@ -3004,17 +3257,17 @@ t_bool qdisable (DEVICE *dptr) { return (dptr->flags & DEV_DIS? TRUE: FALSE); } - -/* find_reg_glob find globally unique register + +/* 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 + 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 + 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) @@ -3023,24 +3276,26 @@ int32 i; DEVICE *dptr; REG *rptr, *srptr = NULL; -for (i = 0; (dptr = sim_devices[i]) != 0; i++) { /* all dev */ - if (dptr->flags & DEV_DIS) continue; /* skip disabled */ - if (rptr = find_reg (cptr, optr, dptr)) { /* found? */ - if (srptr) return NULL; /* ambig? err */ - srptr = rptr; /* save reg */ - *gdptr = dptr; } } /* save unit */ +for (i = 0; (dptr = sim_devices[i]) != 0; i++) { /* all dev */ + if (dptr->flags & DEV_DIS) continue; /* skip disabled */ + 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 +/* 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 + 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 + result = pointer to register, NULL if error + *optr = pointer to next character in input string */ REG *find_reg (char *cptr, char **optr, DEVICE *dptr) @@ -3050,26 +3305,29 @@ REG *rptr; uint32 slnt; if ((cptr == NULL) || (dptr == NULL) || - (dptr->registers == NULL)) return NULL; + (dptr->registers == NULL)) return NULL; tptr = cptr; -do { tptr++; } - while (isalnum (*tptr) || (*tptr == '*') || (*tptr == '_')); +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; } } + 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 +/* get_switches get switches from input string Inputs: - cptr = pointer to input string + cptr = pointer to input string Outputs: - sw = switch bit mask - 0 if no switches, -1 if error + sw = switch bit mask + 0 if no switches, -1 if error */ int32 get_switches (char *cptr) @@ -3079,18 +3337,19 @@ 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)); } + if (isalpha (*cptr) == 0) return -1; + sw = sw | SWMASK (toupper (*cptr)); + } return sw; } -/* get_sim_sw accumulate sim_switches +/* get_sim_sw accumulate sim_switches Inputs: - cptr = pointer to input string + cptr = pointer to input string Outputs: - ptr = pointer to first non-string glyph - NULL if error + ptr = pointer to first non-string glyph + NULL if error */ char *get_sim_sw (char *cptr) @@ -3098,22 +3357,23 @@ 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 */ +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; } -/* get_sim_opt get simulator command options +/* get_sim_opt get simulator command options Inputs: - opt = command options - cptr = pointer to input string + opt = command options + cptr = pointer to input string Outputs: - ptr = pointer to next glypsh, NULL if error - *stat = error status + ptr = pointer to next glypsh, NULL if error + *stat = error status */ char *get_sim_opt (int32 opt, char *cptr, t_stat *st) @@ -3123,54 +3383,59 @@ char *svptr, gbuf[CBUFSIZE]; DEVICE *tdptr; UNIT *tuptr; -sim_switches = 0; /* no switches */ -sim_ofile = NULL; /* no output file */ -sim_schptr = NULL; /* no search */ -sim_stab.logic = SCH_OR; /* default search params */ -sim_stab.bool = SCH_GE; +sim_switches = 0; /* no switches */ +sim_ofile = NULL; /* no output file */ +sim_schptr = NULL; /* no search */ +sim_stab.logic = SCH_OR; /* default search params */ +sim_stab.boolop = SCH_GE; sim_stab.mask = 0; sim_stab.comp = 0; -sim_dfdev = sim_devices[0]; /* default is CPU */ +sim_dfdev = sim_dflt_dev; sim_dfunit = sim_dfdev->units; *st = SCPE_OK; -while (*cptr) { /* loop through modifiers */ - svptr = cptr; /* save current position */ - if ((opt & CMD_OPT_OF) && (*cptr == '@')) { /* output file spec? */ - if (sim_ofile) { /* already got one? */ - fclose (sim_ofile); /* one per customer */ - *st = SCPE_ARG; - return NULL; } - cptr = get_glyph_nc (cptr + 1, gbuf, 0); - sim_ofile = sim_fopen (gbuf, "a"); /* open for append */ - if (sim_ofile) continue; /* if ok, look for more */ - *st = SCPE_OPENERR; /* open failed */ - return NULL; } - cptr = get_glyph (cptr, gbuf, 0); - if ((t = get_switches (gbuf)) != 0) { /* try for switches */ - if (t < 0) { /* err if bad switch */ - *st = SCPE_INVSW; - return NULL; } - sim_switches = sim_switches | t; } /* or in new switches */ - else if ((opt & CMD_OPT_SCH) && /* if allowed, */ - get_search (gbuf, sim_dfdev->dradix, &sim_stab)) /* try for search */ - sim_schptr = &sim_stab; /* set search */ - else if ((opt & CMD_OPT_DFT) && /* if allowed, */ - (tdptr = find_unit (gbuf, &tuptr)) && /* try for default */ - (tuptr != NULL)) { - sim_dfdev = tdptr; /* set as default */ - sim_dfunit = tuptr; } - else return svptr; /* not rec, break out */ - } +while (*cptr) { /* loop through modifiers */ + svptr = cptr; /* save current position */ + if ((opt & CMD_OPT_OF) && (*cptr == '@')) { /* output file spec? */ + if (sim_ofile) { /* already got one? */ + fclose (sim_ofile); /* one per customer */ + *st = SCPE_ARG; + return NULL; + } + cptr = get_glyph_nc (cptr + 1, gbuf, 0); + sim_ofile = sim_fopen (gbuf, "a"); /* open for append */ + if (sim_ofile) continue; /* if ok, look for more */ + *st = SCPE_OPENERR; /* open failed */ + return NULL; + } + cptr = get_glyph (cptr, gbuf, 0); + if ((t = get_switches (gbuf)) != 0) { /* try for switches */ + if (t < 0) { /* err if bad switch */ + *st = SCPE_INVSW; + return NULL; + } + sim_switches = sim_switches | t; /* or in new switches */ + } + else if ((opt & CMD_OPT_SCH) && /* if allowed, */ + get_search (gbuf, sim_dfdev->dradix, &sim_stab)) /* try for search */ + sim_schptr = &sim_stab; /* set search */ + else if ((opt & CMD_OPT_DFT) && /* if allowed, */ + (tdptr = find_unit (gbuf, &tuptr)) && /* try for default */ + (tuptr != NULL)) { + sim_dfdev = tdptr; /* set as default */ + sim_dfunit = tuptr; + } + else return svptr; /* not rec, break out */ + } return cptr; } /* Match file extension Inputs: - fnam = file name - ext = extension, without period + fnam = file name + ext = extension, without period Outputs: - cp = pointer to final '.' if match, NULL if not + cp = pointer to final '.' if match, NULL if not */ char *match_ext (char *fnam, char *ext) @@ -3180,21 +3445,23 @@ 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; } + 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 - radix = radix for numbers - schptr = pointer to search table + cptr = pointer to input string + radix = radix for numbers + schptr = pointer to search table Outputs: - return = NULL if error - schptr if valid search specification + return = NULL if error + schptr if valid search specification */ SCHTAB *get_search (char *cptr, int32 radix, SCHTAB *schptr) @@ -3204,79 +3471,100 @@ 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, radix); - 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, radix); - if (cptr == tptr) return NULL; - cptr = tptr; } - else return NULL; } /* end while */ +logval = cmpval = 0; +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, radix); + if (cptr == tptr) return NULL; + cptr = tptr; + } + else if (sptr = strchr (cmpstr, c)) { /* check for boolop */ + cmpop = sptr - cmpstr; + if (*cptr == '=') { + cmpop = cmpop + strlen (cmpstr); + cptr++; + } + cmpval = strtotv (cptr, &tptr, radix); + if (cptr == tptr) return NULL; + cptr = tptr; + } + else return NULL; + } /* end for */ if (logop >= 0) { - schptr->logic = logop; - schptr->mask = logval; } + schptr->logic = logop; + schptr->mask = logval; + } if (cmpop >= 0) { - schptr->bool = cmpop; - schptr->comp = cmpval; } + schptr->boolop = cmpop; + schptr->comp = cmpval; + } return schptr; } /* Test value against search specification Inputs: - val = value to test - schptr = pointer to search table + val = value to test + schptr = pointer to search table Outputs: - return = 1 if value passes search criteria, 0 if not + 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); } + +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->boolop) { /* 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 + inptr = string to convert + endptr = pointer to first unconverted character + radix = radix for input Outputs: - value = converted value + value = converted value On an error, the endptr will equal the inptr. */ @@ -3287,37 +3575,38 @@ int32 nodigit; t_value val; uint32 c, digit; -*endptr = inptr; /* assume fails */ +*endptr = inptr; /* assume fails */ if ((radix < 2) || (radix > 36)) return 0; -while (isspace (*inptr)) inptr++; /* bypass white space */ +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 */ +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 + stream = stream designator + val = value to print + radix = radix to print + width = width to print + format = leading zeroes format Outputs: - status = error status + status = error status */ t_stat fprint_val (FILE *stream, t_value val, uint32 radix, - uint32 width, uint32 format) + uint32 width, uint32 format) { #define MAX_WIDTH ((int) (CHAR_BIT * sizeof (t_value))) t_value owtest, wtest; @@ -3327,33 +3616,36 @@ 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)); +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; } + 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 + 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 @@ -3369,10 +3661,10 @@ return SCPE_OK; sim_process_event - process event Inputs: - none + none Outputs: - reason reason code returned by any event processor, - or 0 (SCPE_OK) if no exceptions + reason = reason code returned by any event processor, + or 0 (SCPE_OK) if no exceptions */ t_stat sim_process_event (void) @@ -3380,34 +3672,36 @@ 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)); +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 + uptr = pointer to unit + event_time = relative timeout Outputs: - reason = result (SCPE_OK if ok) + reason = result (SCPE_OK if ok) */ t_stat sim_activate (UNIT *uptr, int32 event_time) @@ -3416,33 +3710,37 @@ 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 */ +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; } + 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 + uptr = pointer to unit Outputs: - reason = result (SCPE_OK if ok) + reason = result (SCPE_OK if ok) */ @@ -3451,27 +3749,31 @@ 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 */ +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 */ +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->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 + uptr = pointer to unit Outputs: - result = absolute activation time + 1, 0 if inactive + result = absolute activation time + 1, 0 if inactive */ int32 sim_is_active (UNIT *uptr) @@ -3481,8 +3783,9 @@ int32 accum; accum = 0; for (cptr = sim_clock_queue; cptr != NULL; cptr = cptr->next) { - accum = accum + cptr->time; - if (cptr == uptr) return accum + 1; } + accum = accum + cptr->time; + if (cptr == uptr) return accum + 1; + } return 0; } @@ -3491,20 +3794,20 @@ return 0; Inputs: none Outputs: - time = global time + 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); } +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); } +if (sim_clock_queue == NULL) { UPDATE_SIM_TIME (noqueue_time); } +else { UPDATE_SIM_TIME (sim_clock_queue->time); } return sim_rtime; } @@ -3512,7 +3815,7 @@ return sim_rtime; Inputs: none Outputs: - count = number of entries on the queue + count = number of entries on the queue */ int32 sim_qcount (void) @@ -3524,19 +3827,19 @@ cnt = 0; for (uptr = sim_clock_queue; uptr != NULL; uptr = uptr->next) cnt++; return cnt; } - + /* 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 + 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 @@ -3544,16 +3847,16 @@ return cnt; 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 + 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. */ @@ -3561,7 +3864,7 @@ return cnt; t_stat sim_brk_init (void) { sim_brk_lnt = SIM_BRK_INILNT; -sim_brk_tab = calloc (sim_brk_lnt, sizeof (BRKTAB)); +sim_brk_tab = (BRKTAB *) 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; @@ -3576,19 +3879,21 @@ 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 */ +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 */ +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; } @@ -3600,19 +3905,21 @@ 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); } +if (sim_brk_ent >= sim_brk_lnt) { /* out of space? */ + t = sim_brk_lnt + SIM_BRK_INILNT; /* new size */ + newp = (BRKTAB *) 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; @@ -3630,19 +3937,21 @@ 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 */ +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 = (char *) calloc (CBUFSIZE, sizeof (char)); /* alloc buf */ + 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; } @@ -3653,17 +3962,17 @@ 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 (!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 */ +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; + sim_brk_summ = sim_brk_summ | bp->typ; return SCPE_OK; } @@ -3675,8 +3984,9 @@ 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++; } + if (bp->typ & sw) sim_brk_clr (bp->addr, sw); + else bp++; + } return SCPE_OK; } @@ -3690,16 +4000,18 @@ int32 i, any; if (sw == 0) sw = SIM_BRK_ALLTYP; if (!bp || (!(bp->typ & sw))) return SCPE_OK; -dptr = sim_devices[0]; +dptr = sim_dflt_dev; if (dptr == NULL) return SCPE_OK; if (sim_vm_fprint_addr) sim_vm_fprint_addr (st, dptr, loc); else 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->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"); @@ -3714,7 +4026,8 @@ 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); } + if (bp->typ & sw) sim_brk_show (st, bp->addr, sw); + } return SCPE_OK; } @@ -3724,15 +4037,16 @@ 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; } +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; } @@ -3744,16 +4058,19 @@ 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 */ +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; } @@ -3771,7 +4088,7 @@ void sim_brk_npc (void) sim_brk_pend = FALSE; return; } - + /* Debug printout routines, from Dave Hittner */ const char* debug_bstates = "01_^"; @@ -3791,10 +4108,10 @@ if (dptr->debflags == 0) return debtab_none; /* Find matching words for bitmask */ while (dptr->debflags[offset].name && (offset < 32)) { - if (dptr->debflags[offset].mask & dbits) - return dptr->debflags[offset].name; - offset++; - } + if (dptr->debflags[offset].mask & dbits) + return dptr->debflags[offset].name; + offset++; + } return debtab_nomatch; } @@ -3803,9 +4120,9 @@ return debtab_nomatch; static void sim_debug_prefix (uint32 dbits, DEVICE* dptr) { if (!debug_unterm) { - char* debug_type = get_dbg_verb (dbits, dptr); - fprintf(sim_deb, debug_fmt, dptr->name, debug_type); - } + char* debug_type = get_dbg_verb (dbits, dptr); + fprintf(sim_deb, debug_fmt, dptr->name, debug_type); + } } /* Prints state of a register: bit translation + state (0,1,_,^) @@ -3813,19 +4130,19 @@ if (!debug_unterm) { 0=steady(0->0), 1=steady(1->1), _=falling(1->0), ^=rising(0->1) */ void sim_debug_u16(uint32 dbits, DEVICE* dptr, const char* const* bitdefs, - uint16 before, uint16 after, int terminate) + uint16 before, uint16 after, int terminate) { if (sim_deb && (dptr->dctrl & dbits)) { - int32 i; + int32 i; - sim_debug_prefix(dbits, dptr); /* print prefix if required */ - for (i = 15; i >= 0; i--) { /* print xlation, transition */ - int off = ((after >> i) & 1) + (((before ^ after) >> i) & 1) * 2; - fprintf(sim_deb, "%s%c ", bitdefs[i], debug_bstates[off]); - } - if (terminate) fprintf(sim_deb, "\r\n"); - debug_unterm = terminate ? 0 : 1; /* set unterm for next */ - } + sim_debug_prefix(dbits, dptr); /* print prefix if required */ + for (i = 15; i >= 0; i--) { /* print xlation, transition */ + int off = ((after >> i) & 1) + (((before ^ after) >> i) & 1) * 2; + fprintf(sim_deb, "%s%c ", bitdefs[i], debug_bstates[off]); + } + if (terminate) fprintf(sim_deb, "\r\n"); + debug_unterm = terminate ? 0 : 1; /* set unterm for next */ + } } #if defined (_WIN32) @@ -3850,68 +4167,68 @@ void sim_debug (uint32 dbits, DEVICE* dptr, const char* fmt, ...) { if (sim_deb && (dptr->dctrl & dbits)) { - char stackbuf[STACKBUFSIZE]; - int32 bufsize = sizeof(stackbuf); - char *buf = stackbuf; - va_list arglist; - int32 i, j, len; + char stackbuf[STACKBUFSIZE]; + int32 bufsize = sizeof(stackbuf); + char *buf = stackbuf; + va_list arglist; + int32 i, j, len; - buf[bufsize-1] = '\0'; - sim_debug_prefix(dbits, dptr); /* print prefix if required */ + buf[bufsize-1] = '\0'; + sim_debug_prefix(dbits, dptr); /* print prefix if required */ - while (1) { /* format passed string, args */ - va_start (arglist, fmt); + while (1) { /* format passed string, args */ + va_start (arglist, fmt); #if defined(NO_vsnprintf) #if defined(HAS_vsprintf_void) /* Note, this could blow beyond the buffer, and we couldn't tell */ /* That is a limitation of the C runtime library available on this platform */ - vsprintf (buf, fmt, arglist); - for (len = 0; len < bufsize-1; len++) - if (buf[len] == 0) break; + vsprintf (buf, fmt, arglist); + for (len = 0; len < bufsize-1; len++) + if (buf[len] == 0) break; #else - len = vsprintf (buf, fmt, arglist); -#endif /* HAS_vsprintf_void */ -#else /* NO_vsnprintf */ + len = vsprintf (buf, fmt, arglist); +#endif /* HAS_vsprintf_void */ +#else /* NO_vsnprintf */ #if defined(HAS_vsnprintf_void) - vsnprintf (buf, bufsize-1, fmt, arglist); - for (len = 0; len < bufsize-1; len++) - if (buf[len] == 0) break; + vsnprintf (buf, bufsize-1, fmt, arglist); + for (len = 0; len < bufsize-1; len++) + if (buf[len] == 0) break; #else - len = vsnprintf (buf, bufsize-1, fmt, arglist); -#endif /* HAS_vsnprintf_void */ -#endif /* NO_vsnprintf */ - va_end (arglist); + len = vsnprintf (buf, bufsize-1, fmt, arglist); +#endif /* HAS_vsnprintf_void */ +#endif /* NO_vsnprintf */ + va_end (arglist); /* If it didn't fit into the buffer, then grow it and try again */ - if ((len < 0) || (len >= bufsize-1)) { - if (buf != stackbuf) free (buf); - bufsize = bufsize * 2; - buf = malloc (bufsize); - if (buf == NULL) return; /* out of memory */ - buf[bufsize-1] = '\0'; - continue; - } - break; - } + if ((len < 0) || (len >= bufsize-1)) { + if (buf != stackbuf) free (buf); + bufsize = bufsize * 2; + buf = (char *) malloc (bufsize); + if (buf == NULL) return; /* out of memory */ + buf[bufsize-1] = '\0'; + continue; + } + break; + } /* Output the formatted data expanding newlines where they exist */ - for (i = j = 0; i < len; ++i) { - if ('\n' == buf[i]) { - if (i > j) fwrite (&buf[j], 1, i-j, sim_deb); - j = i; - fputc('\r', sim_deb); - } - } - if (i > j) fwrite (&buf[j], 1, i-j, sim_deb); + for (i = j = 0; i < len; ++i) { + if ('\n' == buf[i]) { + if (i > j) fwrite (&buf[j], 1, i-j, sim_deb); + j = i; + fputc('\r', sim_deb); + } + } + if (i > j) fwrite (&buf[j], 1, i-j, sim_deb); /* Set unterminated flag for next time */ - debug_unterm = (len && (buf[len-1]=='\n')) ? 0 : 1; - if (buf != stackbuf) free (buf); - } + debug_unterm = (len && (buf[len-1]=='\n')) ? 0 : 1; + if (buf != stackbuf) free (buf); + } return; } diff --git a/scp.h b/scp.h index 6ebeac75..bf376b17 100644 --- a/scp.h +++ b/scp.h @@ -23,29 +23,29 @@ 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-05 RMS Added ASSERT command - 09-Sep-04 RMS Added reset_all_p - 14-Feb-04 RMS Added debug prototypes (from Dave Hittner) - 02-Jan-04 RMS Split out from SCP + 07-Feb-05 RMS Added ASSERT command + 09-Sep-04 RMS Added reset_all_p + 14-Feb-04 RMS Added debug prototypes (from Dave Hittner) + 02-Jan-04 RMS Split out from SCP */ #ifndef _SIM_SCP_H_ -#define _SIM_SCP_H_ 0 +#define _SIM_SCP_H_ 0 /* run_cmd parameters */ -#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 RU_RUN 0 /* run */ +#define RU_GO 1 /* go */ +#define RU_STEP 2 /* step */ +#define RU_CONT 3 /* continue */ +#define RU_BOOT 4 /* boot */ /* get_sim_opt parameters */ -#define CMD_OPT_SW 001 /* switches */ -#define CMD_OPT_OF 002 /* output file */ -#define CMD_OPT_SCH 004 /* search */ -#define CMD_OPT_DFT 010 /* defaults */ +#define CMD_OPT_SW 001 /* switches */ +#define CMD_OPT_OF 002 /* output file */ +#define CMD_OPT_SCH 004 /* search */ +#define CMD_OPT_DFT 010 /* defaults */ /* Command processors */ @@ -90,7 +90,7 @@ 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 (DEVICE *dptr, char *cptr, t_addr *lo, t_addr *hi, - uint32 rdx, t_addr max, char term); + 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); @@ -107,7 +107,7 @@ t_bool sim_brk_test (t_addr bloc, int32 btyp); char *match_ext (char *fnam, char *ext); t_stat sim_cancel_step (void); void sim_debug_u16 (uint32 dbits, DEVICE* dptr, const char* const* bitdefs, - uint16 before, uint16 after, int terminate); + uint16 before, uint16 after, int terminate); void sim_debug (uint32 dbits, DEVICE* dptr, const char* fmt, ...); #endif diff --git a/sim_console.c b/sim_console.c index 7030f072..64664558 100644 --- a/sim_console.c +++ b/sim_console.c @@ -1,6 +1,6 @@ /* sim_console.c: simulator console I/O library - Copyright (c) 1993-2004, Robert M Supnik + Copyright (c) 1993-2005, 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"), @@ -19,81 +19,81 @@ 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 + 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. - 05-Nov-04 RMS Moved SET/SHOW DEBUG under CONSOLE hierarchy - 28-Oct-04 JDB Fixed SET CONSOLE to allow comma-separated parameters - 20-Aug-04 RMS Added OS/2 EMX fixes (from Holger Veit) - 14-Jul-04 RMS Revised Windows console code (from Dave Bryan) - 28-May-04 RMS Added SET/SHOW CONSOLE - RMS Added break, delete character maps - 02-Jan-04 RMS Removed timer routines, added Telnet console routines - RMS Moved console logging to OS-independent code - 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 + 05-Nov-04 RMS Moved SET/SHOW DEBUG under CONSOLE hierarchy + 28-Oct-04 JDB Fixed SET CONSOLE to allow comma-separated parameters + 20-Aug-04 RMS Added OS/2 EMX fixes (from Holger Veit) + 14-Jul-04 RMS Revised Windows console code (from Dave Bryan) + 28-May-04 RMS Added SET/SHOW CONSOLE + RMS Added break, delete character maps + 02-Jan-04 RMS Removed timer routines, added Telnet console routines + RMS Moved console logging to OS-independent code + 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: - sim_poll_kbd - poll for keyboard input - sim_putchar - output character to console - sim_putchar_s - output character to console, stall if congested - sim_set_console - set console parameters - sim_show_console - show console parameters + sim_poll_kbd - poll for keyboard input + sim_putchar - output character to console + sim_putchar_s - output character to console, stall if congested + sim_set_console - set console parameters + sim_show_console - show console parameters - sim_ttinit - called once to get initial terminal state - sim_ttrun - called to put terminal into run state - sim_ttcmd - called to return terminal to command state - sim_ttclose - called once before the simulator exits - sim_os_poll_kbd - poll for keyboard input - sim_os_putchar - output character to console + sim_ttinit - called once to get initial terminal state + sim_ttrun - called to put terminal into run state + sim_ttcmd - called to return terminal to command state + sim_ttclose - called once before the simulator exits + sim_os_poll_kbd - poll for keyboard input + sim_os_putchar - output character to console The first group is OS-independent; the second group is OS-dependent. The following routines are exposed but deprecated: - sim_set_telnet - set console to Telnet port - sim_set_notelnet - close console Telnet port - sim_show_telnet - show console status + sim_set_telnet - set console to Telnet port + sim_set_notelnet - close console Telnet port + sim_show_telnet - show console status */ #include "sim_defs.h" #include "sim_sock.h" #include "sim_tmxr.h" -#define KMAP_WRU 0 -#define KMAP_BRK 1 -#define KMAP_DEL 2 -#define KMAP_MASK 0377 -#define KMAP_NZ 0400 +#define KMAP_WRU 0 +#define KMAP_BRK 1 +#define KMAP_DEL 2 +#define KMAP_MASK 0377 +#define KMAP_NZ 0400 -int32 sim_int_char = 005; /* interrupt character */ -int32 sim_brk_char = 000; /* break character */ +int32 sim_int_char = 005; /* interrupt character */ +int32 sim_brk_char = 000; /* break character */ #if defined (_WIN32) || defined (__OS2__) || (defined (__MWERKS__) && defined (macintosh)) -int32 sim_del_char = '\b'; /* delete character */ +int32 sim_del_char = '\b'; /* delete character */ #else int32 sim_del_char = 0177; #endif -TMLN sim_con_ldsc = { 0 }; /* console line descr */ -TMXR sim_con_tmxr = { 1, 0, 0, &sim_con_ldsc }; /* console line mux */ +TMLN sim_con_ldsc = { 0 }; /* console line descr */ +TMXR sim_con_tmxr = { 1, 0, 0, &sim_con_ldsc }; /* console line mux */ extern volatile int32 stop_cpu; extern int32 sim_quiet, sim_deb_close; @@ -103,31 +103,34 @@ extern DEVICE *sim_devices[]; /* Set/show data structures */ static CTAB set_con_tab[] = { - { "WRU", &sim_set_kmap, KMAP_WRU | KMAP_NZ }, - { "BRK", &sim_set_kmap, KMAP_BRK }, - { "DEL", &sim_set_kmap, KMAP_DEL |KMAP_NZ }, - { "TELNET", &sim_set_telnet, 0 }, - { "NOTELNET", &sim_set_notelnet, 0 }, - { "LOG", &sim_set_logon, 0 }, - { "NOLOG", &sim_set_logoff, 0 }, - { "DEBUG", &sim_set_debon, 0 }, - { "NODEBUG", &sim_set_deboff, 0 }, - { NULL, NULL, 0 } }; + { "WRU", &sim_set_kmap, KMAP_WRU | KMAP_NZ }, + { "BRK", &sim_set_kmap, KMAP_BRK }, + { "DEL", &sim_set_kmap, KMAP_DEL |KMAP_NZ }, + { "TELNET", &sim_set_telnet, 0 }, + { "NOTELNET", &sim_set_notelnet, 0 }, + { "LOG", &sim_set_logon, 0 }, + { "NOLOG", &sim_set_logoff, 0 }, + { "DEBUG", &sim_set_debon, 0 }, + { "NODEBUG", &sim_set_deboff, 0 }, + { NULL, NULL, 0 } + }; static SHTAB show_con_tab[] = { - { "WRU", &sim_show_kmap, KMAP_WRU }, - { "BRK", &sim_show_kmap, KMAP_BRK }, - { "DEL", &sim_show_kmap, KMAP_DEL }, - { "LOG", &sim_show_log, 0 }, - { "TELNET", &sim_show_telnet, 0 }, - { "DEBUG", &sim_show_debug, 0 }, - { NULL, NULL, 0 } }; + { "WRU", &sim_show_kmap, KMAP_WRU }, + { "BRK", &sim_show_kmap, KMAP_BRK }, + { "DEL", &sim_show_kmap, KMAP_DEL }, + { "LOG", &sim_show_log, 0 }, + { "TELNET", &sim_show_telnet, 0 }, + { "DEBUG", &sim_show_debug, 0 }, + { NULL, NULL, 0 } + }; static int32 *cons_kmap[] = { - &sim_int_char, - &sim_brk_char, - &sim_del_char }; - + &sim_int_char, + &sim_brk_char, + &sim_del_char + }; + /* Console I/O package. The console terminal can be attached to the controlling window @@ -145,15 +148,16 @@ CTAB *ctptr; t_stat r; if ((cptr == NULL) || (*cptr == 0)) return SCPE_2FARG; -while (*cptr != 0) { /* do all mods */ - cptr = get_glyph_nc (cptr, gbuf, ','); /* get modifier */ - if (cvptr = strchr (gbuf, '=')) *cvptr++ = 0; /* = value? */ - get_glyph (gbuf, gbuf, 0); /* modifier to UC */ - if (ctptr = find_ctab (set_con_tab, gbuf)) { /* match? */ - r = ctptr->action (ctptr->arg, cvptr); /* do the rest */ - if (r != SCPE_OK) return r; } - else return SCPE_NOPARAM; - } +while (*cptr != 0) { /* do all mods */ + cptr = get_glyph_nc (cptr, gbuf, ','); /* get modifier */ + if (cvptr = strchr (gbuf, '=')) *cvptr++ = 0; /* = value? */ + get_glyph (gbuf, gbuf, 0); /* modifier to UC */ + if (ctptr = find_ctab (set_con_tab, gbuf)) { /* match? */ + r = ctptr->action (ctptr->arg, cvptr); /* do the rest */ + if (r != SCPE_OK) return r; + } + else return SCPE_NOPARAM; + } return SCPE_OK; } @@ -165,17 +169,17 @@ char gbuf[CBUFSIZE]; SHTAB *shptr; int32 i; -if (*cptr == 0) { /* show all */ - for (i = 0; show_con_tab[i].name; i++) - show_con_tab[i].action (st, dptr, uptr, show_con_tab[i].arg, cptr); - return SCPE_OK; - } +if (*cptr == 0) { /* show all */ + for (i = 0; show_con_tab[i].name; i++) + show_con_tab[i].action (st, dptr, uptr, show_con_tab[i].arg, cptr); + return SCPE_OK; + } while (*cptr != 0) { - cptr = get_glyph (cptr, gbuf, ','); /* get modifier */ - if (shptr = find_shtab (show_con_tab, gbuf)) - shptr->action (st, dptr, uptr, shptr->arg, cptr); - else return SCPE_NOPARAM; - } + cptr = get_glyph (cptr, gbuf, ','); /* get modifier */ + if (shptr = find_shtab (show_con_tab, gbuf)) + shptr->action (st, dptr, uptr, shptr->arg, cptr); + else return SCPE_NOPARAM; + } return SCPE_OK; } @@ -192,7 +196,7 @@ if (dptr->dradix == 16) rdx = 16; else rdx = 8; val = (int32) get_uint (cptr, rdx, 0177, &r); if ((r != SCPE_OK) || - ((val == 0) && (flag & KMAP_NZ))) return SCPE_ARG; + ((val == 0) && (flag & KMAP_NZ))) return SCPE_ARG; *(cons_kmap[flag & KMAP_MASK]) = val; return SCPE_OK; } @@ -217,14 +221,14 @@ t_stat sim_set_logon (int32 flag, char *cptr) { char gbuf[CBUFSIZE]; -if ((cptr == NULL) || (*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? */ -sim_set_logoff (0, NULL); /* close cur log */ -sim_log = sim_fopen (gbuf, "a"); /* open log */ -if (sim_log == NULL) return SCPE_OPENERR; /* error? */ +if ((cptr == NULL) || (*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? */ +sim_set_logoff (0, NULL); /* close cur log */ +sim_log = sim_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 */ +fprintf (sim_log, "Logging to file \"%s\"\n", gbuf); /* start of log */ return SCPE_OK; } @@ -232,10 +236,10 @@ return SCPE_OK; t_stat sim_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 (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 */ +fprintf (sim_log, "Log file closed\n"); /* close log */ fclose (sim_log); sim_log = NULL; return SCPE_OK; @@ -257,33 +261,36 @@ t_stat sim_set_debon (int32 flag, char *cptr) { char *tptr, gbuf[CBUFSIZE]; -if (*cptr == 0) return SCPE_2FARG; /* need arg */ -tptr = get_glyph (cptr, gbuf, 0); /* get file name */ -if (*tptr != 0) return SCPE_2MARG; /* now eol? */ -sim_set_deboff (0, NULL); /* close cur debug */ -if (strcmp (gbuf, "LOG") == 0) { /* debug to log? */ - if (sim_log == NULL) return SCPE_ARG; /* any log? */ - sim_deb = sim_log; } +if (*cptr == 0) return SCPE_2FARG; /* need arg */ +tptr = get_glyph (cptr, gbuf, 0); /* get file name */ +if (*tptr != 0) return SCPE_2MARG; /* now eol? */ +sim_set_deboff (0, NULL); /* close cur debug */ +if (strcmp (gbuf, "LOG") == 0) { /* debug to log? */ + if (sim_log == NULL) return SCPE_ARG; /* any log? */ + sim_deb = sim_log; + } else if (strcmp (gbuf, "STDOUT") == 0) sim_deb = stdout; /* debug to stdout? */ else if (strcmp (gbuf, "STDERR") == 0) sim_deb = stderr; /* debug to stderr? */ -else { cptr = get_glyph_nc (cptr, gbuf, 0); /* reparse */ - sim_deb = sim_fopen (gbuf, "a"); /* open debug */ - if (sim_deb == NULL) return SCPE_OPENERR; /* error? */ - sim_deb_close = 1; } /* need close */ +else { + cptr = get_glyph_nc (cptr, gbuf, 0); /* reparse */ + sim_deb = sim_fopen (gbuf, "a"); /* open debug */ + if (sim_deb == NULL) return SCPE_OPENERR; /* error? */ + sim_deb_close = 1; /* need close */ + } if (!sim_quiet) printf ("Debug output to \"%s\"\n", gbuf); if (sim_log) fprintf (sim_log, "Debug output to \"%s\"\n", gbuf); return SCPE_OK; } - /* Set nodebug routine */ +/* Set nodebug routine */ t_stat sim_set_deboff (int32 flag, char *cptr) { -if (cptr && (*cptr != 0)) return SCPE_2MARG; /* now eol? */ -if (sim_deb == NULL) return SCPE_OK; /* no log? */ +if (cptr && (*cptr != 0)) return SCPE_2MARG; /* now eol? */ +if (sim_deb == NULL) return SCPE_OK; /* no log? */ if (!sim_quiet) printf ("Debug output disabled\n"); if (sim_log) fprintf (sim_log, "Debug output disabled\n"); -if (sim_deb_close) fclose (sim_deb); /* close if needed */ +if (sim_deb_close) fclose (sim_deb); /* close if needed */ sim_deb_close = 0; sim_deb = NULL; return SCPE_OK; @@ -303,18 +310,18 @@ return SCPE_OK; t_stat sim_set_telnet (int32 flg, char *cptr) { -if ((cptr == NULL) || (*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 */ +if ((cptr == NULL) || (*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 sim_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 */ +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 */ @@ -323,13 +330,15 @@ t_stat sim_show_telnet (FILE *st, DEVICE *dunused, UNIT *uunused, int32 flag, ch { if (cptr && (*cptr != 0)) return SCPE_2MARG; if (sim_con_tmxr.master == 0) - fprintf (st, "Connected to console window\n"); + 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); } + 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; } @@ -339,25 +348,29 @@ 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 */ +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 */ @@ -366,13 +379,13 @@ 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; +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; } @@ -380,12 +393,12 @@ return SCPE_OK; t_stat sim_putchar (int32 c) { -if (sim_log) fputc (c, sim_log); /* log file? */ -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 */ +if (sim_log) fputc (c, sim_log); /* log file? */ +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; } @@ -393,16 +406,16 @@ t_stat sim_putchar_s (int32 c) { t_stat r; -if (sim_log) fputc (c, sim_log); /* log file? */ -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? */ -if (sim_con_ldsc.xmte == 0) r = SCPE_STALL; /* xmt disabled? */ -else r = tmxr_putc_ln (&sim_con_ldsc, c); /* no, Telnet output */ -tmxr_poll_tx (&sim_con_tmxr); /* poll xmt */ -return r; /* return status */ +if (sim_log) fputc (c, sim_log); /* log file? */ +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? */ +if (sim_con_ldsc.xmte == 0) r = SCPE_STALL; /* xmt disabled? */ +else r = tmxr_putc_ln (&sim_con_ldsc, c); /* no, Telnet output */ +tmxr_poll_tx (&sim_con_tmxr); /* poll xmt */ +return r; /* return status */ } - + /* VMS routines, from Ben Thomas, with fixes from Robert Alan Byer */ #if defined (VMS) @@ -424,16 +437,16 @@ return r; /* return status */ uint32 tty_chan = 0; typedef struct { - unsigned short sense_count; - unsigned char sense_first_char; - unsigned char sense_reserved; - unsigned int stat; - unsigned int stat2; } SENSE_BUF; + unsigned short sense_count; + unsigned char sense_first_char; + unsigned char sense_reserved; + unsigned int stat; + unsigned int stat2; } SENSE_BUF; typedef struct { - unsigned short status; - unsigned short count; - unsigned int dev_status; } IOSB; + unsigned short status; + unsigned short count; + unsigned int dev_status; } IOSB; SENSE_BUF cmd_mode = { 0 }; SENSE_BUF run_mode = { 0 }; @@ -447,7 +460,7 @@ $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); + &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); @@ -461,7 +474,7 @@ 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); + &run_mode, sizeof (run_mode), 0, 0, 0, 0); if ((status != SS$_NORMAL) || (iosb.status != SS$_NORMAL)) return SCPE_TTIERR; return SCPE_OK; } @@ -472,7 +485,7 @@ 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); + &cmd_mode, sizeof (cmd_mode), 0, 0, 0, 0); if ((status != SS$_NORMAL) || (iosb.status != SS$_NORMAL)) return SCPE_TTIERR; return SCPE_OK; } @@ -491,13 +504,13 @@ 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); + 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); + 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; if (sim_brk_char && (buf[0] == sim_brk_char)) return SCPE_BREAK; @@ -512,11 +525,11 @@ IOSB iosb; c = out; status = sys$qiow (EFN, tty_chan, IO$_WRITELBLK | IO$M_NOFORMAT, - &iosb, 0, 0, &c, 1, 0, 0, 0, 0); + &iosb, 0, 0, &c, 1, 0, 0, 0, 0); if ((status != SS$_NORMAL) || (iosb.status != SS$_NORMAL)) return SCPE_TTOERR; return SCPE_OK; } - + /* Win32 routines */ #elif defined (_WIN32) @@ -533,17 +546,18 @@ t_stat sim_ttinit (void) { std_input = GetStdHandle (STD_INPUT_HANDLE); if ((std_input == INVALID_HANDLE_VALUE) || - !GetConsoleMode (std_input, &saved_mode)) return SCPE_TTYERR; + !GetConsoleMode (std_input, &saved_mode)) return SCPE_TTYERR; return SCPE_OK; } t_stat sim_ttrun (void) { if (!GetConsoleMode(std_input, &saved_mode) || - !SetConsoleMode(std_input, RAW_MODE)) return SCPE_TTYERR; + !SetConsoleMode(std_input, RAW_MODE)) return SCPE_TTYERR; if (sim_log) { - fflush (sim_log); - _setmode (_fileno (sim_log), _O_BINARY); } + fflush (sim_log); + _setmode (_fileno (sim_log), _O_BINARY); + } SetThreadPriority (GetCurrentThread(), THREAD_PRIORITY_BELOW_NORMAL); return SCPE_OK; } @@ -551,8 +565,9 @@ return SCPE_OK; t_stat sim_ttcmd (void) { if (sim_log) { - fflush (sim_log); - _setmode (_fileno (sim_log), _O_TEXT); } + fflush (sim_log); + _setmode (_fileno (sim_log), _O_TEXT); + } SetThreadPriority (GetCurrentThread(), THREAD_PRIORITY_NORMAL); if (!SetConsoleMode(std_input, saved_mode)) return SCPE_TTYERR; return SCPE_OK; @@ -580,7 +595,7 @@ t_stat sim_os_putchar (int32 c) if (c != 0177) _putch (c); return SCPE_OK; } - + /* OS/2 routines, from Bruce Ray and Holger Veit */ #elif defined (__OS2__) @@ -612,14 +627,18 @@ t_stat sim_os_poll_kbd (void) int c; #if defined (__EMX__) -switch (c = _read_kbd(0,0,0)) { /* EMX has _read_kbd */ -case -1: /* no char*/ - return SCPE_OK; -case 0: /* char pending */ - c = _read_kbd(0,1,0); - break; -default: /* got char */ - break; } +switch (c = _read_kbd(0,0,0)) { /* EMX has _read_kbd */ + + case -1: /* no char*/ + return SCPE_OK; + + case 0: /* char pending */ + c = _read_kbd(0,1,0); + break; + + default: /* got char */ + break; + } #else if (!kbhit ()) return SCPE_OK; c = getch(); @@ -634,14 +653,15 @@ t_stat sim_os_putchar (int32 c) { if (c != 0177) { #if defined (__EMX__) - putchar (c); + putchar (c); #else - putch (c); + putch (c); #endif - fflush (stdout); } + fflush (stdout); + } return SCPE_OK; } - + /* Metrowerks CodeWarrior Macintosh routines, from Louis Chretien and Peter Schorn */ @@ -667,114 +687,116 @@ int ps_getch(void); extern char sim_name[]; extern pSIOUXWin SIOUXTextWindow; -static CursHandle iBeamCursorH = NULL; /* contains the iBeamCursor */ +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); + WindowPtr window; + window = FrontWindow(); + if (SIOUXIsAppWindow(window)) { + GrafPtr savePort; + Point localMouse; + GetPort(&savePort); + SetPort(window); #if TARGET_API_MAC_CARBON - GetGlobalMouse(&localMouse); + GetGlobalMouse(&localMouse); #else - localMouse = LMGetMouseLocation(); + 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; + 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; - } + 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); - } + 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 sim_ttinit (void) { /* Note that this only works if the call to sim_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 sim_ttinit (void) { + int i; + /* this blank will later be replaced by the number of characters */ + char title[50] = " "; + 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 sim_ttrun (void) @@ -807,11 +829,12 @@ return c | SCPE_KFLAG; t_stat sim_os_putchar (int32 c) { if (c != 0177) { - putchar (c); - fflush (stdout); } + putchar (c); + fflush (stdout); + } return SCPE_OK; } - + /* BSD UNIX routines */ #elif defined (BSDTTY) @@ -820,50 +843,50 @@ return SCPE_OK; #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 */ +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 sim_ttinit (void) { -cmdfl = fcntl (0, F_GETFL, 0); /* get old flags and status */ +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 = 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_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_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 */ +return SCPE_OK; /* return success */ } t_stat sim_ttrun (void) { -runtchars.t_intrc = sim_int_char; /* in case changed */ -fcntl (0, F_SETFL, runfl); /* non-block mode */ +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 */ +nice (10); /* lower priority */ return SCPE_OK; } t_stat sim_ttcmd (void) { -nice (-10); /* restore priority */ -fcntl (0, F_SETFL, cmdfl); /* block mode */ +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; @@ -894,7 +917,7 @@ c = out; write (1, &c, 1); return SCPE_OK; } - + /* POSIX UNIX routines, from Leendert Van Doorn */ #else @@ -907,23 +930,23 @@ static int prior_norm = 1; t_stat sim_ttinit (void) { -if (!isatty (fileno (stdin))) return SCPE_OK; /* skip if !tty */ -if (tcgetattr (0, &cmdtty) < 0) return SCPE_TTIERR; /* get old flags */ +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_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[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 */ +runtty.c_cc[VREPRINT] = 0; /* no specials */ #endif #if defined (VDISCARD) runtty.c_cc[VDISCARD] = 0; @@ -934,7 +957,7 @@ runtty.c_cc[VWERASE] = 0; #if defined (VLNEXT) runtty.c_cc[VLNEXT] = 0; #endif -runtty.c_cc[VMIN] = 0; /* no waiting */ +runtty.c_cc[VMIN] = 0; /* no waiting */ runtty.c_cc[VTIME] = 0; #if defined (VDSUSP) runtty.c_cc[VDSUSP] = 0; @@ -947,23 +970,25 @@ return SCPE_OK; t_stat sim_ttrun (void) { -if (!isatty (fileno (stdin))) return SCPE_OK; /* skip if !tty */ -runtty.c_cc[VINTR] = sim_int_char; /* in case changed */ +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 */ +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 sim_ttcmd (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 (!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; } diff --git a/sim_console.h b/sim_console.h index 1c789656..769bfcb2 100644 --- a/sim_console.h +++ b/sim_console.h @@ -1,6 +1,6 @@ /* sim_console.h: simulator console I/O library headers - Copyright (c) 1993-2004, Robert M Supnik + Copyright (c) 1993-2005, 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"), @@ -19,17 +19,17 @@ 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 + 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. - 05-Nov-04 RMS Moved SET/SHOW DEBUG under CONSOLE hierarchy - 28-May-04 RMS Added SET/SHOW CONSOLE - 02-Jan-04 RMS Removed timer routines, added Telnet console routines + 05-Nov-04 RMS Moved SET/SHOW DEBUG under CONSOLE hierarchy + 28-May-04 RMS Added SET/SHOW CONSOLE + 02-Jan-04 RMS Removed timer routines, added Telnet console routines */ #ifndef _SIM_CONSOLE_H_ -#define _SIM_CONSOLE_H_ 0 +#define _SIM_CONSOLE_H_ 0 t_stat sim_set_console (int32 flag, char *cptr); t_stat sim_set_kmap (int32 flag, char *cptr); diff --git a/sim_defs.h b/sim_defs.h index 9e1fea88..55b3cc05 100644 --- a/sim_defs.h +++ b/sim_defs.h @@ -19,78 +19,79 @@ 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 + 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. - 11-Mar-05 RMS Moved 64b data type definitions outside USE_INT64 - 07-Feb-05 RMS Added assertion fail stop - 05-Nov-04 RMS Added support for SHOW opt=val - 20-Oct-04 RMS Converted all base types to typedefs - 21-Sep-04 RMS Added switch to flag stop message printout - 06-Feb-04 RMS Moved device and unit user flags fields (V3.2) - RMS Added REG_VMAD - 29-Dec-03 RMS Added output stall status - 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 + 16-Aug-05 RMS Fixed C++ declaration and cast problems + 11-Mar-05 RMS Moved 64b data type definitions outside USE_INT64 + 07-Feb-05 RMS Added assertion fail stop + 05-Nov-04 RMS Added support for SHOW opt=val + 20-Oct-04 RMS Converted all base types to typedefs + 21-Sep-04 RMS Added switch to flag stop message printout + 06-Feb-04 RMS Moved device and unit user flags fields (V3.2) + RMS Added REG_VMAD + 29-Dec-03 RMS Added output stall status + 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 + 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 + print_sym print symbolic output + parse_sym parse symbolic input */ #ifndef _SIM_DEFS_H_ -#define _SIM_DEFS_H_ 0 +#define _SIM_DEFS_H_ 0 #include #include @@ -101,138 +102,138 @@ #include #ifndef TRUE -#define TRUE 1 -#define FALSE 0 +#define TRUE 1 +#define FALSE 0 #endif /* Length specific integer declarations */ -typedef signed char int8; -typedef signed short int16; -typedef signed int int32; -typedef unsigned char uint8; -typedef unsigned short uint16; -typedef unsigned int uint32; -typedef int t_stat; /* status */ -typedef int t_bool; /* boolean */ +typedef signed char int8; +typedef signed short int16; +typedef signed int int32; +typedef unsigned char uint8; +typedef unsigned short uint16; +typedef unsigned int uint32; +typedef int t_stat; /* status */ +typedef int t_bool; /* boolean */ /* 64b integers */ -#if defined (__GNUC__) /* GCC */ -typedef signed long long t_int64; -typedef unsigned long long t_uint64; -#elif defined (_WIN32) /* Windows */ -typedef signed __int64 t_int64; -typedef unsigned __int64 t_uint64; -#elif defined (__ALPHA) && defined (VMS) /* Alpha VMS */ -typedef signed __int64 t_int64; -typedef unsigned __int64 t_uint64; -#elif defined (__ALPHA) && defined (__unix__) /* Alpha UNIX */ -typedef signed long t_int64; -typedef unsigned long t_uint64; -#else /* default */ -#define t_int64 signed long long -#define t_uint64 unsigned long long -#endif /* end 64b */ +#if defined (__GNUC__) /* GCC */ +typedef signed long long t_int64; +typedef unsigned long long t_uint64; +#elif defined (_WIN32) /* Windows */ +typedef signed __int64 t_int64; +typedef unsigned __int64 t_uint64; +#elif defined (__ALPHA) && defined (VMS) /* Alpha VMS */ +typedef signed __int64 t_int64; +typedef unsigned __int64 t_uint64; +#elif defined (__ALPHA) && defined (__unix__) /* Alpha UNIX */ +typedef signed long t_int64; +typedef unsigned long t_uint64; +#else /* default */ +#define t_int64 signed long long +#define t_uint64 unsigned long long +#endif /* end 64b */ -#if defined (USE_INT64) /* 64b data */ -typedef t_int64 t_svalue; /* signed value */ -typedef t_uint64 t_value; /* value */ -#else /* 32b data */ -typedef int32 t_svalue; -typedef uint32 t_value; -#endif /* end 64b data */ +#if defined (USE_INT64) /* 64b data */ +typedef t_int64 t_svalue; /* signed value */ +typedef t_uint64 t_value; /* value */ +#else /* 32b data */ +typedef int32 t_svalue; +typedef uint32 t_value; +#endif /* end 64b data */ -#if defined (USE_INT64) && defined (USE_ADDR64) /* 64b address */ -typedef t_uint64 t_addr; -#define T_ADDR_W 64 -#else /* 32b address */ -typedef uint32 t_addr; -#define T_ADDR_W 32 -#endif /* end 64b address */ +#if defined (USE_INT64) && defined (USE_ADDR64) /* 64b address */ +typedef t_uint64 t_addr; +#define T_ADDR_W 64 +#else /* 32b address */ +typedef uint32 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 +#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 */ +#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 */ -#define SIM_SW_STOP (1u << 29) /* stop message */ - +#define SIM_SW_HIDE (1u << 26) /* enable hiding */ +#define SIM_SW_REST (1u << 27) /* attach/restore */ +#define SIM_SW_REG (1u << 28) /* register value */ +#define SIM_SW_STOP (1u << 29) /* stop message */ + /* Simulator status codes - 0 ok - 1 - (SCPE_BASE - 1) simulator specific - SCPE_BASE - n general + 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_STALL (SCPE_BASE + 41) /* Telnet conn stall */ -#define SCPE_AFAIL (SCPE_BASE + 42) /* assert failed */ -#define SCPE_KFLAG 0010000 /* tti data flag */ -#define SCPE_BREAK 0020000 /* tti break flag */ +#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_STALL (SCPE_BASE + 41) /* Telnet conn stall */ +#define SCPE_AFAIL (SCPE_BASE + 42) /* assert failed */ +#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 */ +#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 */ +#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 */ @@ -241,63 +242,63 @@ typedef uint32 t_addr; /* 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 */ - uint32 dctrl; /* debug control */ - struct sim_debtab *debflags; /* debug flags */ - t_stat (*msize)(struct sim_unit *up, int32 v, char *cp, void *dp); - /* mem size routine */ - char *lname; /* logical name */ - }; + 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 */ + uint32 dctrl; /* debug control */ + struct sim_debtab *debflags; /* debug 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 disabled */ -#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_DEBUG 4 /* debug capability */ -#define DEV_V_RAW 5 /* raw supported */ -#define DEV_V_RAWONLY 6 /* only raw supported */ -#define DEV_V_UF_31 12 /* user flags, V3.1 */ -#define DEV_V_UF 16 /* user flags */ -#define DEV_V_RSV 31 /* reserved */ +#define DEV_V_DIS 0 /* dev disabled */ +#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_DEBUG 4 /* debug capability */ +#define DEV_V_RAW 5 /* raw supported */ +#define DEV_V_RAWONLY 6 /* only raw supported */ +#define DEV_V_UF_31 12 /* user flags, V3.1 */ +#define DEV_V_UF 16 /* 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_DEBUG (1 << DEV_V_DEBUG) -#define DEV_RAW (1 << DEV_V_RAW) -#define DEV_RAWONLY (1 << DEV_V_RAWONLY) +#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_DEBUG (1 << DEV_V_DEBUG) +#define DEV_RAW (1 << DEV_V_RAW) +#define DEV_RAWONLY (1 << DEV_V_RAWONLY) -#define DEV_UFMASK_31 (((1u << DEV_V_RSV) - 1) & ~((1u << DEV_V_UF_31) - 1)) -#define DEV_UFMASK (((1u << DEV_V_RSV) - 1) & ~((1u << DEV_V_UF) - 1)) -#define DEV_RFLAGS (DEV_UFMASK|DEV_DIS) /* restored flags */ +#define DEV_UFMASK_31 (((1u << DEV_V_RSV) - 1) & ~((1u << DEV_V_UF_31) - 1)) +#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 @@ -309,150 +310,150 @@ struct sim_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 */ - }; + 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_31 12 /* dev spec, V3.1 */ -#define UNIT_V_UF 16 /* device specific */ -#define UNIT_V_RSV 31 /* reserved!! */ +#define UNIT_V_UF_31 12 /* dev spec, V3.1 */ +#define UNIT_V_UF 16 /* 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_RAW 010000 /* raw mode */ +#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_RAW 010000 /* raw mode */ + +#define UNIT_UFMASK_31 (((1u << UNIT_V_RSV) - 1) & ~((1u << UNIT_V_UF_31) - 1)) +#define UNIT_UFMASK (((1u << UNIT_V_RSV) - 1) & ~((1u << UNIT_V_UF) - 1)) +#define UNIT_RFLAGS (UNIT_UFMASK|UNIT_DIS) /* restored flags */ -#define UNIT_UFMASK_31 (((1u << UNIT_V_RSV) - 1) & ~((1u << UNIT_V_UF_31) - 1)) -#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 */ - }; + 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 data print/parse */ -#define REG_VMAD 0400 /* use VM addr print/parse */ -#define REG_HRO (REG_RO | REG_HIDDEN) /* hidden, read only */ +#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 data print/parse */ +#define REG_VMAD 0400 /* use VM addr 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 */ - }; + 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, char *cptr); /* action routine */ - int32 arg; /* argument */ - char *help; /* help string */ - }; + char *name; /* name */ + t_stat (*action)(struct sim_device *dptr, struct sim_unit *uptr, + int32 flag, char *cptr); /* action routine */ + int32 arg; /* argument */ + char *help; /* help string */ + }; struct sim_shtab { - char *name; /* name */ - t_stat (*action)(FILE *st, struct sim_device *dptr, - struct sim_unit *uptr, int32 flag, char *cptr); - int32 arg; /* argument */ - char *help; /* help string */ - }; + char *name; /* name */ + t_stat (*action)(FILE *st, struct sim_device *dptr, + struct sim_unit *uptr, 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 */ - }; + 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 */ -#define MTAB_SHP 040 /* show takes parameter */ +#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 */ +#define MTAB_SHP 040 /* show takes parameter */ /* 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 */ - }; + int32 logic; /* logical operator */ + int32 boolop; /* 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 */ - }; + t_addr addr; /* address */ + int32 typ; /* mask of types */ + int32 cnt; /* proceed count */ + char *act; /* action string */ + }; /* Debug table */ struct sim_debtab { - char *name; /* control name */ - uint32 mask; /* control bit */ - }; + char *name; /* control name */ + uint32 mask; /* control bit */ + }; + +#define DEBUG_PRS(d) (sim_deb && d.dctrl) +#define DEBUG_PRD(d) (sim_deb && d->dctrl) +#define DEBUG_PRI(d,m) (sim_deb && (d.dctrl & (m))) -#define DEBUG_PRS(d) (sim_deb && d.dctrl) -#define DEBUG_PRD(d) (sim_deb && d->dctrl) -#define DEBUG_PRI(d,m) (sim_deb && (d.dctrl & (m))) - /* The following macros define structure contents */ #define UDATA(act,fl,cap) NULL,act,NULL,NULL,NULL,0,0,(fl),(cap),0,0 @@ -465,7 +466,7 @@ struct sim_debtab { #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) + #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 @@ -474,7 +475,7 @@ struct sim_debtab { #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) + "nm", &(loc), (rdx), (wd), (off), (dep), ((fl) | REG_UNIT) #endif /* Typedefs for principal structures */ @@ -489,7 +490,7 @@ typedef struct sim_mtab MTAB; typedef struct sim_schtab SCHTAB; typedef struct sim_brktab BRKTAB; typedef struct sim_debtab DEBTAB; - + /* Function prototypes */ #include "scp.h" diff --git a/sim_ether.c b/sim_ether.c index 438148a7..85ee81f0 100644 --- a/sim_ether.c +++ b/sim_ether.c @@ -1,6 +1,6 @@ /* sim_ether.c: OS-dependent network routines ------------------------------------------------------------------------------ - Copyright (c) 2002-2004, David T. Hittner + Copyright (c) 2002-2005, 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"), @@ -134,6 +134,7 @@ Modification history: + 01-Dec-04 DTH Added Windows user-defined adapter names (from Timothe Litt) 25-Mar-04 MP Revised comments and minor #defines to deal with updated libpcap which now provides pcap_sendpacket on all platforms. 04-Feb-04 MP Returned success/fail status from eth_write to support @@ -399,6 +400,31 @@ char* eth_getname(int number, char* name) return name; } +char* eth_getname_bydesc(char* desc, char* name) +{ + ETH_LIST list[ETH_MAX_DEVICE]; + int count = eth_devices(ETH_MAX_DEVICE, list); + int i; + int j=strlen(desc); + + for (i=0; iitem) { size_t size = sizeof(struct eth_item) * max; que->max = max; - que->item = malloc(size); + que->item = (struct eth_item *) malloc(size); if (que->item) { /* init dynamic memory */ memset(que->item, 0, size); @@ -533,6 +559,11 @@ int eth_devices (int max, ETH_LIST* dev) #include #include +/* Allows windows to look up user-defined adapter names */ +#if defined(_WIN32) +#include +#endif + /* Some platforms have always had pcap_sendpacket */ #if defined(_WIN32) || defined(VMS) #define HAS_PCAP_SENDPACKET 1 @@ -619,6 +650,13 @@ t_stat eth_open(ETH_DEV* dev, char* name, DEVICE* dptr, uint32 dbit) ) { num = atoi(&name[3]); savname = eth_getname(num, temp); + if (savname == 0) /* didn't translate */ + return SCPE_OPENERR; + } else { + /* are they trying to use device description? */ + savname = eth_getname_bydesc(name, temp); + if (savname == 0) /* didn't translate */ + return SCPE_OPENERR; } /* attempt to connect device */ @@ -1074,8 +1112,45 @@ int eth_host_devices(int used, int max, ETH_LIST* list) list[i+j] = list[i+j+1]; --used; } - } - return used; + } /* for */ + +#if defined(_WIN32) + /* replace device description with user-defined adapter name (if defined) */ + for (i=0; i sizeof(regval))) { + RegCloseKey (reghnd); + continue; + } + /* registry value seems OK, finish up and replace description */ + RegCloseKey (reghnd ); + sprintf (list[i].desc, "%s", regval); + } + } /* for */ +#endif + + return used; } int eth_devices(int max, ETH_LIST* list) diff --git a/sim_ether.h b/sim_ether.h index b96078bd..2a8e1d76 100644 --- a/sim_ether.h +++ b/sim_ether.h @@ -1,7 +1,7 @@ /* sim_ether.h: OS-dependent network information ------------------------------------------------------------------------------ - Copyright (c) 2002-2004, David T. Hittner + Copyright (c) 2002-2005, 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"), @@ -100,14 +100,14 @@ /* 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_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 */ -#define ETH_MAX_DEVICE 10 /* maximum ethernet devices */ +#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_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 */ +#define ETH_MAX_DEVICE 10 /* maximum ethernet devices */ #define DECNET_SELF_FRAME(dnet_mac, msg) \ ((memcmp(dnet_mac, msg , 6) == 0) && \ @@ -121,7 +121,7 @@ struct eth_packet { }; struct eth_item { - int type; /* receive (0=setup, 1=loopback, 2=normal) */ + int type; /* receive (0=setup, 1=loopback, 2=normal) */ struct eth_packet packet; }; @@ -150,25 +150,25 @@ typedef struct eth_queue ETH_QUE; typedef struct eth_item ETH_ITEM; 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 */ - int addr_count; /* count of filtering addresses */ - ETH_BOOL promiscuous; /* promiscuous mode flag */ - ETH_BOOL all_multicast; /* receive all multicast messages */ - int32 decnet_self_sent; /* loopback packets sent but not seen */ - ETH_MAC decnet_addr; /* decnet address of interface */ - DEVICE* dptr; /* device ethernet is attached to */ - uint32 dbit; /* debugging bit */ - int reflections; /* packet reflections on interface */ + 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 */ + int addr_count; /* count of filtering addresses */ + ETH_BOOL promiscuous; /* promiscuous mode flag */ + ETH_BOOL all_multicast; /* receive all multicast messages */ + int32 decnet_self_sent; /* loopback packets sent but not seen */ + ETH_MAC decnet_addr; /* decnet address of interface */ + DEVICE* dptr; /* device ethernet is attached to */ + uint32 dbit; /* debugging bit */ + int reflections; /* packet reflections on interface */ #if defined (USE_READER_THREAD) ETH_QUE read_queue; pthread_mutex_t lock; - pthread_t reader_thread; /* Reader Thread Id */ + pthread_t reader_thread; /* Reader Thread Id */ #endif }; @@ -176,31 +176,31 @@ typedef struct eth_device ETH_DEV; /* prototype declarations*/ -t_stat eth_open (ETH_DEV* dev, char* name, /* open ethernet interface */ +t_stat eth_open (ETH_DEV* dev, char* name, /* open ethernet interface */ DEVICE* dptr, uint32 dbit); -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 */ +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 */ +int eth_devices (int max, ETH_LIST* dev); /* get ethernet devices on host */ void eth_packet_trace (ETH_DEV* dev, const uint8 *msg, int len, char* txt); /* trace ethernet packet */ -t_stat eth_show (FILE* st, UNIT* uptr, /* show ethernet devices */ +t_stat eth_show (FILE* st, UNIT* uptr, /* show ethernet devices */ int32 val, void* desc); -void eth_mac_fmt (ETH_MAC* add, char* buffer); /* format ethernet mac address */ -t_stat eth_mac_scan (ETH_MAC* mac, char* strmac); /* scan string for mac, put in mac */ +void eth_mac_fmt (ETH_MAC* add, char* buffer); /* format ethernet mac address */ +t_stat eth_mac_scan (ETH_MAC* mac, char* strmac); /* scan string for mac, put in mac */ -t_stat ethq_init (ETH_QUE* que, int max); /* initialize FIFO queue */ -void ethq_clear (ETH_QUE* que); /* clear FIFO queue */ -void ethq_remove (ETH_QUE* que); /* remove item from FIFO queue */ -void ethq_insert (ETH_QUE* que, int32 type, /* insert item into FIFO queue */ +t_stat ethq_init (ETH_QUE* que, int max); /* initialize FIFO queue */ +void ethq_clear (ETH_QUE* que); /* clear FIFO queue */ +void ethq_remove (ETH_QUE* que); /* remove item from FIFO queue */ +void ethq_insert (ETH_QUE* que, int32 type, /* insert item into FIFO queue */ ETH_PACK* packet, int32 status); -#endif /* _SIM_ETHER_H */ +#endif /* _SIM_ETHER_H */ diff --git a/sim_fio.c b/sim_fio.c index 0d245fc1..30ea2863 100644 --- a/sim_fio.c +++ b/sim_fio.c @@ -1,6 +1,6 @@ /* sim_fio.c: simulator file I/O library - Copyright (c) 1993-2004, Robert M Supnik + Copyright (c) 1993-2005, 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"), @@ -19,22 +19,23 @@ 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 + 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-Jul-04 RMS Fixed bug in optimized sim_fread (reported by Scott Bailey) - 26-May-04 RMS Optimized sim_fread (suggested by John Dundas) - 02-Jan-04 RMS Split out from SCP + 16-Aug-05 RMS Fixed C++ declaration and cast problems + 17-Jul-04 RMS Fixed bug in optimized sim_fread (reported by Scott Bailey) + 26-May-04 RMS Optimized sim_fread (suggested by John Dundas) + 02-Jan-04 RMS Split out from SCP This library includes: - sim_finit - initialize package - sim_fopen - open file - sim_fread - endian independent read (formerly fxread) - sim_write - endian independent write (formerly fxwrite) - sim_fseek - extended (>32b) seek (formerly fseek_ext) - sim_fsize - get file size + sim_finit - initialize package + sim_fopen - open file + sim_fread - endian independent read (formerly fxread) + sim_write - endian independent write (formerly fxwrite) + sim_fseek - extended (>32b) seek (formerly fseek_ext) + sim_fsize - get file size sim_fopen and sim_fseek are OS-dependent. The other routines are not. sim_fsize is always a 32b routine (it is used only with small capacity random @@ -44,8 +45,8 @@ #include "sim_defs.h" static unsigned char sim_flip[FLIP_SIZE]; -int32 sim_end = 1; /* 1 = little */ - +int32 sim_end = 1; /* 1 = little */ + /* OS-independent, endian independent binary I/O package For consistency, all binary data read and written by the simulator @@ -67,7 +68,7 @@ int32 sim_finit (void) { union {int32 i; char c[sizeof (int32)]; } end_test; -end_test.i = 1; /* test endian-ness */ +end_test.i = 1; /* test endian-ness */ sim_end = end_test.c[0]; return sim_end; } @@ -78,16 +79,18 @@ size_t c, j; int32 k; unsigned char by, *sptr, *dptr; -if ((size == 0) || (count == 0)) return 0; /* check arguments */ -c = fread (bptr, size, count, fptr); /* read buffer */ -if (sim_end || (size == sizeof (char)) || (c == 0)) /* le, byte, or err? */ - return c; /* done */ -for (j = 0, dptr = sptr = bptr; j < c; j++) { /* loop on items */ - for (k = size - 1; k >= (((int32) size + 1) / 2); k--) { - by = *sptr; /* swap end-for-end */ - *sptr++ = *(dptr + k); - *(dptr + k) = by; } - sptr = dptr = dptr + size; } /* next item */ +if ((size == 0) || (count == 0)) return 0; /* check arguments */ +c = fread (bptr, size, count, fptr); /* read buffer */ +if (sim_end || (size == sizeof (char)) || (c == 0)) /* le, byte, or err? */ + return c; /* done */ +for (j = 0, dptr = sptr = (unsigned char *) bptr; j < c; j++) { /* loop on items */ + for (k = size - 1; k >= (((int32) size + 1) / 2); k--) { + by = *sptr; /* swap end-for-end */ + *sptr++ = *(dptr + k); + *(dptr + k) = by; + } + sptr = dptr = dptr + size; /* next item */ + } return c; } @@ -97,24 +100,26 @@ size_t c, j, nelem, nbuf, lcnt, total; int32 i, k; unsigned char *sptr, *dptr; -if ((size == 0) || (count == 0)) return 0; /* check arguments */ -if (sim_end || (size == sizeof (char))) /* le or byte? */ - return fwrite (bptr, size, count, fptr); /* done */ -nelem = FLIP_SIZE / size; /* elements in buffer */ -nbuf = count / nelem; /* number buffers */ -lcnt = count % nelem; /* count in last buf */ +if ((size == 0) || (count == 0)) return 0; /* check arguments */ +if (sim_end || (size == sizeof (char))) /* le or byte? */ + return fwrite (bptr, size, count, fptr); /* done */ +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--) { /* loop on buffers */ - c = (i == 1)? lcnt: nelem; - for (j = 0, dptr = sim_flip; j < c; j++) { /* loop on items */ - 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; } +sptr = (unsigned char *) bptr; /* init input ptr */ +for (i = nbuf; i > 0; i--) { /* loop on buffers */ + c = (i == 1)? lcnt: nelem; + for (j = 0, dptr = sim_flip; j < c; j++) { /* loop on items */ + 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; } @@ -131,16 +136,16 @@ sz = ftell (fp); fseek (fp, pos, SEEK_SET); return sz; } - + /* OS-dependent routines */ /* Optimized file open */ -FILE *sim_fopen (char *file, char *mode) +FILE *sim_fopen (const char *file, const char *mode) { #if defined (VMS) return fopen (file, mode, "ALQ=32", "DEQ=4096", - "MBF=6", "MBC=127", "FOP=cbt,tef", "ROP=rah,wbh", "CTX=stm"); + "MBF=6", "MBC=127", "FOP=cbt,tef", "ROP=rah,wbh", "CTX=stm"); #elif defined (USE_INT64) && defined (USE_ADDR64) && defined (linux) return fopen64 (file, mode); #else @@ -154,12 +159,12 @@ return fopen (file, mode); /* Alpha VMS */ -#if defined (__ALPHA) && defined (VMS) /* Alpha VMS */ -#define _SIM_IO_FSEEK_EXT_ 1 +#if defined (__ALPHA) && defined (VMS) /* Alpha VMS */ +#define _SIM_IO_FSEEK_EXT_ 1 static t_int64 fpos_t_to_int64 (fpos_t *pos) { -unsigned short *w = (unsigned short *) pos; /* endian dep! */ +unsigned short *w = (unsigned short *) pos; /* endian dep! */ t_int64 result; result = w[1]; @@ -183,8 +188,10 @@ 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; } + w[2] = bufsize; + w[0] -= mbc; + } +return; } int sim_fseek (FILE *st, t_addr offset, int whence) @@ -193,17 +200,22 @@ 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); } + + 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); } @@ -212,8 +224,8 @@ return fsetpos (st, &filepos); /* Alpha UNIX - natively 64b */ -#if defined (__ALPHA) && defined (__unix__) /* Alpha UNIX */ -#define _SIM_IO_FSEEK_EXT_ 1 +#if defined (__ALPHA) && defined (__unix__) /* Alpha UNIX */ +#define _SIM_IO_FSEEK_EXT_ 1 int sim_fseek (FILE *st, t_addr offset, int whence) { @@ -225,46 +237,51 @@ return fseek (st, offset, whence); /* Windows */ #if defined (_WIN32) -#define _SIM_IO_FSEEK_EXT_ 1 +#define _SIM_IO_FSEEK_EXT_ 1 int sim_fseek (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); } + + 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 Windows */ /* Linux */ #if defined (linux) -#define _SIM_IO_FSEEK_EXT_ 1 +#define _SIM_IO_FSEEK_EXT_ 1 int sim_fseek (FILE *st, t_addr xpos, int origin) { return fseeko64 (st, xpos, origin); } -#endif /* end Linux with LFS */ +#endif /* end Linux with LFS */ -#endif /* end 64b seek defs */ +#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 +#define _SIM_IO_FSEEK_EXT_ 0 int sim_fseek (FILE *st, t_addr xpos, int origin) { diff --git a/sim_fio.h b/sim_fio.h index e9af1ca4..9a9f8098 100644 --- a/sim_fio.h +++ b/sim_fio.h @@ -1,6 +1,6 @@ /* sim_fio.h: simulator file I/O library headers - Copyright (c) 1993-2004, Robert M Supnik + Copyright (c) 1993-2005, 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"), @@ -19,22 +19,23 @@ 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 + Except as contained in this notice, the name of Robert M Supnik shall not be 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. - 02-Jan-04 RMS Split out from SCP + 16-Aug-05 RMS Fixed C++ declaration and cast problems + 02-Jan-04 RMS Split out from SCP */ #ifndef _SIM_FIO_H_ -#define _SIM_FIO_H_ 0 +#define _SIM_FIO_H_ 0 -#define FLIP_SIZE (1 << 16) /* flip buf size */ -#define fxread(a,b,c,d) sim_fread (a, b, c, d) -#define fxwrite(a,b,c,d) sim_fwrite (a, b, c, d) +#define FLIP_SIZE (1 << 16) /* flip buf size */ +#define fxread(a,b,c,d) sim_fread (a, b, c, d) +#define fxwrite(a,b,c,d) sim_fwrite (a, b, c, d) int32 sim_finit (void); -FILE *sim_fopen (char *file, char *mode); +FILE *sim_fopen (const char *file, const char *mode); int sim_fseek (FILE *st, t_addr offset, int whence); size_t sim_fread (void *bptr, size_t size, size_t count, FILE *fptr); size_t sim_fwrite (void *bptr, size_t size, size_t count, FILE *fptr); diff --git a/sim_rev.h b/sim_rev.h index d7a0c8d3..b397647a 100644 --- a/sim_rev.h +++ b/sim_rev.h @@ -19,1416 +19,1483 @@ 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 + 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_REV_H_ 0 -#define SIM_MAJOR 3 -#define SIM_MINOR 4 -#define SIM_PATCH 0 +#define SIM_MAJOR 3 +#define SIM_MINOR 5 +#define SIM_PATCH 0 + +/* V3.5 revision history + +patch date module(s) and fix(es) + + 0 1-Sep-05 Note: most source modules have been edited to improve + readability and to fix declaration and cast problems in C++ + + all instruction histories: fixed reversed arguments to calloc + + scp.c: revised to trim trailing spaces on file inputs + + sim_sock.c: fixed SIGPIPE error on Unix + + sim_ether.c: added Windows user-defined adapter names (from Timothe Litt) + + sim_tape.c: fixed misallocation of TPC map array + + sim_tmxr.c: added support for SET DISCONNECT + + hp2100_mux.c: added SET MUXLn DISCONNECT + + i1401_cpu.c: + - fixed SSB-SSG clearing on RESET (reported by Ralph Reinke) + - removed error stops in MCE + + i1401_cd.c: fixed read, punch to ignore modifier on 1, 4 char inst + (reported by Van Snyder) + + id_pas.c: + - fixed bug in SHOW CONN/STATS + - added SET PASLn DISCONNECT + + pdp10_ksio.c: revised for new autoconfiguration interface + + pdp11_cpu.c: replaced WAIT clock queue check with API call + + pdp11_cpumod.c: added additional 11/60 registers + + pdp11_io.c: revised autoconfiguration algorithm and interface + + pdp11_dz.c: revised for new autoconfiguration interface + + pdp11_vh.c: + - revised for new autoconfiguration interface + - fixed bug in vector display routine + + pdp11_xu.c: fixed runt packet processing (found by Tim Chapman) + + pdp18b_cpu.c, pdp18b_sys.c: + - removed spurious AAS instruction + + pdp18b_tt1.c: + - fixed bug in SHOW CONN/STATS + - fixed bug in SET LOG/NOLOG + - added SET TTOXn DISCONNECT + + pdp8_ttx.c: + - fixed bug in SHOW CONN/STATS + - fixed bug in SET LOG/NOLOG + - added SET TTOXn DISCONNECT + + sds_mux.c: + - fixed bug in SHOW CONN/STATS + - added SET MUXLn DISCONNECT + + vaxmod_defs.h: added QDSS support + + vax_io.c: revised autoconfiguration algorithm and interface /* V3.4 revision history -patch date module(s) and fix(es) + 0 01-May-04 scp.c: + - fixed ASSERT code + - revised syntax for SET DEBUG (from Dave Bryan) + - revised interpretation of fprint_sym, fparse_sym returns + - moved DETACH sanity tests into detach_unit - 0 01-May-04 scp.c: - - fixed ASSERT code - - revised syntax for SET DEBUG (from Dave Bryan) - - revised interpretation of fprint_sym, fparse_sym returns - - moved DETACH sanity tests into detach_unit + sim_sock.h and sim_sock.c: + - added test for WSAEINPROGRESS (from Tim Riker) - sim_sock.h and sim_sock.c: - - added test for WSAEINPROGRESS (from Tim Riker) + many: revised detach routines to test for attached state - many: revised detach routines to test for attached state + hp2100_cpu.c: reorganized CPU options (from Dave Bryan) - hp2100_cpu.c: reorganized CPU options (from Dave Bryan) + hp2100_cpu1.c: reorganized EIG routines (from Dave Bryan) - hp2100_cpu1.c: reorganized EIG routines (from Dave Bryan) + hp2100_fp1.c: added FFP support (from Dave Bryan) - hp2100_fp1.c: added FFP support (from Dave Bryan) + id16_cpu.c: + - fixed bug in show history routine (from Mark Hittinger) + - revised examine/deposit to do words rather than bytes - id16_cpu.c: - - fixed bug in show history routine (from Mark Hittinger) - - revised examine/deposit to do words rather than bytes + id32_cpu.c: + - fixed bug in initial memory allocation + - fixed bug in show history routine (from Mark Hittinger) + - revised examine/deposit to do words rather than bytes - id32_cpu.c: - - fixed bug in initial memory allocation - - fixed bug in show history routine (from Mark Hittinger) - - revised examine/deposit to do words rather than bytes + id16_sys.c, id32_sys: + - revised examine/deposit to do words rather than bytes - id16_sys.c, id32_sys: - - revised examine/deposit to do words rather than bytes + pdp10_tu.c: + - fixed bug, ERASE and WREOF should not clear done (reported + by Rich Alderson) + - fixed error reporting - pdp10_tu.c: - - fixed bug, ERASE and WREOF should not clear done (reported - by Rich Alderson) - - fixed error reporting - - pdp11_tu.c: fixed error reporting + pdp11_tu.c: fixed error reporting /* V3.3 revision history - 2 08-Mar-05 scp.c: added ASSERT command (from Dave Bryan) + 2 08-Mar-05 scp.c: added ASSERT command (from Dave Bryan) - h316_defs.h: fixed IORETURN macro + h316_defs.h: fixed IORETURN macro - h316_mt.c: fixed error reporting from OCP (found by Philipp Hachtmann) + h316_mt.c: fixed error reporting from OCP (found by Philipp Hachtmann) - h316_stddev.c: fixed bug in OCP '0001 (found by Philipp Hachtmann) + h316_stddev.c: fixed bug in OCP '0001 (found by Philipp Hachtmann) - hp2100_cpu.c: split out EAU and MAC instructions + hp2100_cpu.c: split out EAU and MAC instructions - hp2100_cpu1.c: (from Dave Bryan) - - fixed missing MPCK on JRS target - - removed EXECUTE instruction (is NOP in actual microcode) + hp2100_cpu1.c: (from Dave Bryan) + - fixed missing MPCK on JRS target + - removed EXECUTE instruction (is NOP in actual microcode) - hp2100_fp: (from Dave Bryan) - - fixed missing negative overflow renorm in StoreFP + hp2100_fp: (from Dave Bryan) + - fixed missing negative overflow renorm in StoreFP - i1401_lp.c: fixed bug in write_line (reported by Van Snyder) + i1401_lp.c: fixed bug in write_line (reported by Van Snyder) - id32_cpu.c: fixed branches to mask new PC (from Greg Johnson) + id32_cpu.c: fixed branches to mask new PC (from Greg Johnson) - pdp11_cpu.c: fixed bugs in RESET for 11/70 (reported by Tim Chapman) + pdp11_cpu.c: fixed bugs in RESET for 11/70 (reported by Tim Chapman) - pdp11_cpumod.c: - - fixed bug in SHOW MODEL (from Sergey Okhapkin) - - made SYSID variable for 11/70 (from Tim Chapman) - - added MBRK write case for 11/70 (from Tim Chapman) + pdp11_cpumod.c: + - fixed bug in SHOW MODEL (from Sergey Okhapkin) + - made SYSID variable for 11/70 (from Tim Chapman) + - added MBRK write case for 11/70 (from Tim Chapman) - pdp11_rq: added RA60, RA71, RA81 disks + pdp11_rq: added RA60, RA71, RA81 disks - pdp11_ry: fixed bug in boot code (reported by Graham Toal) + pdp11_ry: fixed bug in boot code (reported by Graham Toal) - vax_cpu.c: fixed initial state of cpu_extmem + vax_cpu.c: fixed initial state of cpu_extmem - 1 05-Jan-05 h316_cpu.c: fixed bug in DIV + 1 05-Jan-05 h316_cpu.c: fixed bug in DIV - h316_stddev.c: - - fixed bug in SKS '104 (reported by Philipp Hachtmann) - - fixed bug in SKS '504 - - adder reader/punch ASCII file support - - added Teletype reader/punch support + h316_stddev.c: + - fixed bug in SKS '104 (reported by Philipp Hachtmann) + - fixed bug in SKS '504 + - adder reader/punch ASCII file support + - added Teletype reader/punch support - h316_dp.c: fixed bug in skip on !seeking + h316_dp.c: fixed bug in skip on !seeking - h316_mt.c: fixed bug in DMA/DMC support + h316_mt.c: fixed bug in DMA/DMC support - h316_lp.c: fixed bug in DMA/DMC support + h316_lp.c: fixed bug in DMA/DMC support - hp2100_cpu.c: - - fixed DMA reset to clear alternate CTL flop (from Dave Bryan) - - fixed DMA reset to not clear control words (from Dave Bryan) - - fixed SBS, CBS, TBS to do virtual reads - - separated A/B from M[0/1], for DMA IO (from Dave Bryan) - - added SET CPU 21MX-M, 21MX-E (from Dave Brian) - - disabled TIMER/EXECUTE/DIAG instructions for 21MX-M (from Dave Bryan) - - added post-processor to maintain T/M consistency (from Dave Bryan) + hp2100_cpu.c: + - fixed DMA reset to clear alternate CTL flop (from Dave Bryan) + - fixed DMA reset to not clear control words (from Dave Bryan) + - fixed SBS, CBS, TBS to do virtual reads + - separated A/B from M[0/1], for DMA IO (from Dave Bryan) + - added SET CPU 21MX-M, 21MX-E (from Dave Brian) + - disabled TIMER/EXECUTE/DIAG instructions for 21MX-M (from Dave Bryan) + - added post-processor to maintain T/M consistency (from Dave Bryan) - hp2100_ds.c: first release + hp2100_ds.c: first release - hp2100_lps.c (all changes from Dave Bryan) - - added restart when set online, etc. - - fixed col count for non-printing chars + hp2100_lps.c (all changes from Dave Bryan) + - added restart when set online, etc. + - fixed col count for non-printing chars - hp2100_lpt.c (all changes from Dave Bryan) - - added restart when set online, etc. + hp2100_lpt.c (all changes from Dave Bryan) + - added restart when set online, etc. - hp2100_sys.c (all changes from Dave Bryan): - - added STOP_OFFLINE, STOP_PWROFF messages + hp2100_sys.c (all changes from Dave Bryan): + - added STOP_OFFLINE, STOP_PWROFF messages - i1401_sys.c: added address argument support (from Van Snyder) + i1401_sys.c: added address argument support (from Van Snyder) - id_mt.c: added read-only file support + id_mt.c: added read-only file support - lgp_cpu.c, lgp_sys.c: modified VM pointer setup + lgp_cpu.c, lgp_sys.c: modified VM pointer setup - pdp11_cpu.c: fixed WAIT to work in all modes (from John Dundas) + pdp11_cpu.c: fixed WAIT to work in all modes (from John Dundas) - pdp11_tm.c, pdp11_ts.c: added read-only file support + pdp11_tm.c, pdp11_ts.c: added read-only file support - sds_mt.c: added read-only file support + sds_mt.c: added read-only file support - 0 23-Nov-04 scp.c: - - added reset_all_p (powerup) - - fixed comma-separated SET options (from Dave Bryan) - - changed ONLINE/OFFLINE to ENABLED/DISABLED (from Dave Bryan) - - modified to flush device buffers on stop (from Dave Bryan) - - changed HELP to suppress duplicate command displays + 0 23-Nov-04 scp.c: + - added reset_all_p (powerup) + - fixed comma-separated SET options (from Dave Bryan) + - changed ONLINE/OFFLINE to ENABLED/DISABLED (from Dave Bryan) + - modified to flush device buffers on stop (from Dave Bryan) + - changed HELP to suppress duplicate command displays - sim_console.c: - - moved SET/SHOW DEBUG under CONSOLE hierarchy + sim_console.c: + - moved SET/SHOW DEBUG under CONSOLE hierarchy - hp2100_cpu.c: (all fixes by Dave Bryan) - - moved MP into its own device; added MP option jumpers - - modified DMA to allow disabling - - modified SET CPU 2100/2116 to truncate memory > 32K - - added -F switch to SET CPU to force memory truncation - - fixed S-register behavior on 2116 - - fixed LIx/MIx behavior for DMA on 2116 and 2100 - - fixed LIx/MIx behavior for empty I/O card slots - - modified WRU to be REG_HRO - - added BRK and DEL to save console settings - - fixed use of "unsigned int16" in cpu_reset + hp2100_cpu.c: (all fixes by Dave Bryan) + - moved MP into its own device; added MP option jumpers + - modified DMA to allow disabling + - modified SET CPU 2100/2116 to truncate memory > 32K + - added -F switch to SET CPU to force memory truncation + - fixed S-register behavior on 2116 + - fixed LIx/MIx behavior for DMA on 2116 and 2100 + - fixed LIx/MIx behavior for empty I/O card slots + - modified WRU to be REG_HRO + - added BRK and DEL to save console settings + - fixed use of "unsigned int16" in cpu_reset - hp2100_dp.c: (all fixes by Dave Bryan) - - fixed enable/disable from either device - - fixed ANY ERROR status for 12557A interface - - fixed unattached drive status for 12557A interface - - status cmd without prior STC DC now completes (12557A) - - OTA/OTB CC on 13210A interface also does CLC CC - - fixed RAR model - - fixed seek check on 13210 if sector out of range + hp2100_dp.c: (all fixes by Dave Bryan) + - fixed enable/disable from either device + - fixed ANY ERROR status for 12557A interface + - fixed unattached drive status for 12557A interface + - status cmd without prior STC DC now completes (12557A) + - OTA/OTB CC on 13210A interface also does CLC CC + - fixed RAR model + - fixed seek check on 13210 if sector out of range - hp2100_dq.c: (all fixes by Dave Bryan) - - fixed enable/disable from either device - - shortened xtime from 5 to 3 (drive avg 156KW/second) - - fixed not ready/any error status - - fixed RAR model + hp2100_dq.c: (all fixes by Dave Bryan) + - fixed enable/disable from either device + - shortened xtime from 5 to 3 (drive avg 156KW/second) + - fixed not ready/any error status + - fixed RAR model - hp2100_dr.c: (all fixes by Dave Bryan) - - fixed enable/disable from either device - - fixed sector return in status word - - provided protected tracks and "Writing Enabled" status bit - - fixed DMA last word write, incomplete sector fill value - - added "parity error" status return on writes for 12606 - - added track origin test for 12606 - - added SCP test for 12606 - - fixed 12610 SFC operation - - added "Sector Flag" status bit - - added "Read Inhibit" status bit for 12606 - - fixed current-sector determination - - added TRACKPROT modifier + hp2100_dr.c: (all fixes by Dave Bryan) + - fixed enable/disable from either device + - fixed sector return in status word + - provided protected tracks and "Writing Enabled" status bit + - fixed DMA last word write, incomplete sector fill value + - added "parity error" status return on writes for 12606 + - added track origin test for 12606 + - added SCP test for 12606 + - fixed 12610 SFC operation + - added "Sector Flag" status bit + - added "Read Inhibit" status bit for 12606 + - fixed current-sector determination + - added TRACKPROT modifier - hp2100_ipl.c, hp2100_ms.c: (all fixes by Dave Bryan) - - fixed enable/disable from either device + hp2100_ipl.c, hp2100_ms.c: (all fixes by Dave Bryan) + - fixed enable/disable from either device - hp2100_lps.c: (all fixes by Dave Bryan) - - added SET OFFLINE/ONLINE, POWEROFF/POWERON - - fixed status returns for error conditions - - fixed handling of non-printing characters - - fixed handling of characters after column 80 - - improved timing model accuracy for RTE - - added fast/realistic timing - - added debug printouts + hp2100_lps.c: (all fixes by Dave Bryan) + - added SET OFFLINE/ONLINE, POWEROFF/POWERON + - fixed status returns for error conditions + - fixed handling of non-printing characters + - fixed handling of characters after column 80 + - improved timing model accuracy for RTE + - added fast/realistic timing + - added debug printouts - hp2100_lpt.c: (all fixes by Dave Bryan) - - added SET OFFLINE/ONLINE, POWEROFF/POWERON - - fixed status returns for error conditions - - fixed TOF handling so form remains on line 0 + hp2100_lpt.c: (all fixes by Dave Bryan) + - added SET OFFLINE/ONLINE, POWEROFF/POWERON + - fixed status returns for error conditions + - fixed TOF handling so form remains on line 0 - hp2100_stddev.c (all fixes by Dave Bryan) - - added paper tape loop mode, DIAG/READER modifiers to PTR - - added PV_LEFT to PTR TRLLIM register - - modified CLK to permit disable + hp2100_stddev.c (all fixes by Dave Bryan) + - added paper tape loop mode, DIAG/READER modifiers to PTR + - added PV_LEFT to PTR TRLLIM register + - modified CLK to permit disable - hp2100_sys.c: (all fixes by Dave Bryan) - - added memory protect device - - fixed display of CCA/CCB/CCE instructions + hp2100_sys.c: (all fixes by Dave Bryan) + - added memory protect device + - fixed display of CCA/CCB/CCE instructions - i1401_cpu.c: added =n to SHOW HISTORY + i1401_cpu.c: added =n to SHOW HISTORY - id16_cpu.c: added instruction history + id16_cpu.c: added instruction history - id32_cpu.c: added =n to SHOW HISTORY + id32_cpu.c: added =n to SHOW HISTORY - pdp10_defs.h: revised Unibus DMA API's + pdp10_defs.h: revised Unibus DMA API's - pdp10_ksio.c: revised Unibus DMA API's + pdp10_ksio.c: revised Unibus DMA API's - pdp10_lp20.c: revised Unibus DMA API's + pdp10_lp20.c: revised Unibus DMA API's - pdp10_rp.c: replicated register state per drive + pdp10_rp.c: replicated register state per drive - pdp10_tu.c: - - fixed to set FCE on short record - - fixed to return bit<15> in drive type - - fixed format specification, 1:0 are don't cares - - implemented write check - - TMK is cleared by new motion command, not DCLR - - DONE is set on data transfers, ATA on non data transfers - - pdp11_defs.h: - - revised Unibus/Qbus DMA API's - - added CPU type and options flags - - pdp11_cpumod.h, pdp11_cpumod.c: - - new routines for setting CPU type and options + pdp10_tu.c: + - fixed to set FCE on short record + - fixed to return bit<15> in drive type + - fixed format specification, 1:0 are don't cares + - implemented write check + - TMK is cleared by new motion command, not DCLR + - DONE is set on data transfers, ATA on non data transfers + + pdp11_defs.h: + - revised Unibus/Qbus DMA API's + - added CPU type and options flags + + pdp11_cpumod.h, pdp11_cpumod.c: + - new routines for setting CPU type and options - pdp11_io.c: revised Unibus/Qbus DMA API's - - all PDP-11 DMA peripherals: - - revised Unibus/Qbus DMA API's - - pdp11_hk.c: CS2 OR must be zero for M+ - - pdp11_rh.c, pdp11_rp.c, pdp11_tu.c: - - split Massbus adapter from controllers - - replicated RP register state per drive - - added TM02/TM03 with TE16/TU45/TU77 drives + pdp11_io.c: revised Unibus/Qbus DMA API's + + all PDP-11 DMA peripherals: + - revised Unibus/Qbus DMA API's + + pdp11_hk.c: CS2 OR must be zero for M+ + + pdp11_rh.c, pdp11_rp.c, pdp11_tu.c: + - split Massbus adapter from controllers + - replicated RP register state per drive + - added TM02/TM03 with TE16/TU45/TU77 drives - pdp11_rq.c, pdp11_tq.c: - - provided different default timing for PDP-11, VAX - - revised to report CPU bus type in stage 1 - - revised to report controller type reflecting bus type - - added -L switch (LBNs) to RAUSER size specification + pdp11_rq.c, pdp11_tq.c: + - provided different default timing for PDP-11, VAX + - revised to report CPU bus type in stage 1 + - revised to report controller type reflecting bus type + - added -L switch (LBNs) to RAUSER size specification - pdp15_cpu.c: added =n to SHOW HISTORY + pdp15_cpu.c: added =n to SHOW HISTORY - pdp15_fpp.c: - - fixed URFST to mask low 9b of fraction - - fixed exception PC setting + pdp15_fpp.c: + - fixed URFST to mask low 9b of fraction + - fixed exception PC setting - pdp8_cpu.c: added =n to SHOW HISTORY + pdp8_cpu.c: added =n to SHOW HISTORY - vax_defs.h: - - added octaword, compatibility mode support + vax_defs.h: + - added octaword, compatibility mode support - vax_moddefs.h: - - revised Unibus/Qbus DMA API's + vax_moddefs.h: + - revised Unibus/Qbus DMA API's - vax_cpu.c: - - moved processor-specific code to vax_sysdev.c - - added =n to SHOW HISTORY + vax_cpu.c: + - moved processor-specific code to vax_sysdev.c + - added =n to SHOW HISTORY - vax_cpu1.c: - - moved processor-specific IPR's to vax_sysdev.c - - moved emulation trap to vax_cis.c - - added support for compatibility mode + vax_cpu1.c: + - moved processor-specific IPR's to vax_sysdev.c + - moved emulation trap to vax_cis.c + - added support for compatibility mode - vax_cis.c: new full VAX CIS instruction emulator + vax_cis.c: new full VAX CIS instruction emulator - vax_octa.c: new full VAX octaword and h_floating instruction emulator + vax_octa.c: new full VAX octaword and h_floating instruction emulator - vax_cmode.c: new full VAX compatibility mode instruction emulator + vax_cmode.c: new full VAX compatibility mode instruction emulator - vax_io.c: - - revised Unibus/Qbus DMA API's + vax_io.c: + - revised Unibus/Qbus DMA API's - vax_io.c, vax_stddev.c, vax_sysdev.c: - - integrated powerup into RESET (with -p) + vax_io.c, vax_stddev.c, vax_sysdev.c: + - integrated powerup into RESET (with -p) - vax_sys.c: - - fixed bugs in parsing indirect displacement modes - - fixed bugs in displaying and parsing character data + vax_sys.c: + - fixed bugs in parsing indirect displacement modes + - fixed bugs in displaying and parsing character data - vax_syscm.c: added display and parse for compatibility mode + vax_syscm.c: added display and parse for compatibility mode - vax_syslist.c: - - split from vax_sys.c - - removed PTR, PTP + vax_syslist.c: + - split from vax_sys.c + - removed PTR, PTP /* V3.2 revision history - 3 03-Sep-04 scp.c: - - added ECHO command (from Dave Bryan) - - qualified RESTORE detach with SIM_SW_REST + 3 03-Sep-04 scp.c: + - added ECHO command (from Dave Bryan) + - qualified RESTORE detach with SIM_SW_REST - sim_console: added OS/2 EMX fixes (from Holger Veit) + sim_console: added OS/2 EMX fixes (from Holger Veit) - sim_sock.h: added missing definition for OS/2 (from Holger Veit) + sim_sock.h: added missing definition for OS/2 (from Holger Veit) - hp2100_cpu.c: changed error stops to report PC not PC + 1 - (from Dave Bryan) + hp2100_cpu.c: changed error stops to report PC not PC + 1 + (from Dave Bryan) - hp2100_dp.c: functional and timing fixes (from Dave Bryan) - - controller sets ATN for all commands except read status - - controller resumes polling for ATN interrupts after read status - - check status on unattached drive set busy and not ready - - check status tests wrong unit for write protect status - - drive on line sets ATN, will set FLG if polling + hp2100_dp.c: functional and timing fixes (from Dave Bryan) + - controller sets ATN for all commands except read status + - controller resumes polling for ATN interrupts after read status + - check status on unattached drive set busy and not ready + - check status tests wrong unit for write protect status + - drive on line sets ATN, will set FLG if polling - hp2100_dr.c: fixed CLC to stop operation (from Dave Bryan) + hp2100_dr.c: fixed CLC to stop operation (from Dave Bryan) - hp2100_ms.c: functional and timing fixes (from Dave Bryan) - - fixed erroneous execution of rejected command - - fixed erroneous execution of select-only command - - fixed erroneous execution of clear command - - fixed odd byte handling for read - - fixed spurious odd byte status on 13183A EOF - - modified handling of end of medium - - added detailed timing, with fast and realistic modes - - added reel sizes to simulate end of tape - - added debug printouts + hp2100_ms.c: functional and timing fixes (from Dave Bryan) + - fixed erroneous execution of rejected command + - fixed erroneous execution of select-only command + - fixed erroneous execution of clear command + - fixed odd byte handling for read + - fixed spurious odd byte status on 13183A EOF + - modified handling of end of medium + - added detailed timing, with fast and realistic modes + - added reel sizes to simulate end of tape + - added debug printouts - hp2100_mt.c: modified handling of end of medium (from Dave Bryan) + hp2100_mt.c: modified handling of end of medium (from Dave Bryan) - hp2100_stddev.c: added tab to control char set (from Dave Bryan) + hp2100_stddev.c: added tab to control char set (from Dave Bryan) - pdp11_rq.c: VAX controllers luns start at 0 (from Andreas Cejna) + pdp11_rq.c: VAX controllers luns start at 0 (from Andreas Cejna) - vax_cpu.c: fixed bug in EMODD/G, second word of quad dst not probed + vax_cpu.c: fixed bug in EMODD/G, second word of quad dst not probed - 2 17-Jul-04 scp.c: fixed problem ATTACHing to read only files - (found by John Dundas) + 2 17-Jul-04 scp.c: fixed problem ATTACHing to read only files + (found by John Dundas) - sim_console.c: revised Windows console code (from Dave Bryan) + sim_console.c: revised Windows console code (from Dave Bryan) - sim_fio.c: fixed problem in big-endian read - (reported by Scott Bailey) + sim_fio.c: fixed problem in big-endian read + (reported by Scott Bailey) - gri_cpu.c: updated MSR, EAO functions + gri_cpu.c: updated MSR, EAO functions - hp_stddev.c: generalized handling of control char echoing - (from Dave Bryan) + hp_stddev.c: generalized handling of control char echoing + (from Dave Bryan) - vax_sys.c: fixed bad block initialization routine + vax_sys.c: fixed bad block initialization routine - 1 10-Jul-04 scp.c: added SET/SHOW CONSOLE subhierarchy + 1 10-Jul-04 scp.c: added SET/SHOW CONSOLE subhierarchy - hp2100_cpu.c: fixes and added features (from Dave Bryan) - - SBT increments B after store - - DMS console map must check dms_enb - - SFS x,C and SFC x,C work - - MP violation clears automatically on interrupt - - SFS/SFC 5 is not gated by protection enabled - - DMS enable does not disable mem prot checks - - DMS status inconsistent at simulator halt - - Examine/deposit are checking wrong addresses - - Physical addresses are 20b not 15b - - Revised DMS to use memory rather than internal format - - Added instruction printout to HALT message - - Added M and T internal registers - - Added N, S, and U breakpoints - Revised IBL facility to conform to microcode - Added DMA EDT I/O pseudo-opcode - Separated DMA SRQ (service request) from FLG + hp2100_cpu.c: fixes and added features (from Dave Bryan) + - SBT increments B after store + - DMS console map must check dms_enb + - SFS x,C and SFC x,C work + - MP violation clears automatically on interrupt + - SFS/SFC 5 is not gated by protection enabled + - DMS enable does not disable mem prot checks + - DMS status inconsistent at simulator halt + - Examine/deposit are checking wrong addresses + - Physical addresses are 20b not 15b + - Revised DMS to use memory rather than internal format + - Added instruction printout to HALT message + - Added M and T internal registers + - Added N, S, and U breakpoints + Revised IBL facility to conform to microcode + Added DMA EDT I/O pseudo-opcode + Separated DMA SRQ (service request) from FLG - all HP2100 peripherals: - - revised to make SFS x,C and SFC x,C work - - revised to separate SRQ from FLG + all HP2100 peripherals: + - revised to make SFS x,C and SFC x,C work + - revised to separate SRQ from FLG - all HP2100 IBL bootable peripherals: - - revised boot ROMs to use IBL facility - - revised SR values to preserve SR<5:3> + all HP2100 IBL bootable peripherals: + - revised boot ROMs to use IBL facility + - revised SR values to preserve SR<5:3> - hp2100_lps.c, hp2100_lpt.c: fixed timing - - hp2100_dp.c: fixed interpretation of SR<0> + hp2100_lps.c, hp2100_lpt.c: fixed timing + + hp2100_dp.c: fixed interpretation of SR<0> - hp2100_dr.c: revised boot code to use IBL algorithm + hp2100_dr.c: revised boot code to use IBL algorithm - hp2100_mt.c, hp2100_ms.c: fixed spurious timing error after CLC - (found by Dave Bryan) + hp2100_mt.c, hp2100_ms.c: fixed spurious timing error after CLC + (found by Dave Bryan) - hp2100_stddev.c: - - fixed input behavior during typeout for RTE-IV - - suppressed nulls on TTY output for RTE-IV + hp2100_stddev.c: + - fixed input behavior during typeout for RTE-IV + - suppressed nulls on TTY output for RTE-IV - hp2100_sys.c: added SFS x,C and SFC x,C to print/parse routines + hp2100_sys.c: added SFS x,C and SFC x,C to print/parse routines - pdp10_fe.c, pdp11_stddev.c, pdp18b_stddev.c, pdp8_tt.c, vax_stddev.c: - - removed SET TTI CTRL-C option + pdp10_fe.c, pdp11_stddev.c, pdp18b_stddev.c, pdp8_tt.c, vax_stddev.c: + - removed SET TTI CTRL-C option - pdp11_tq.c: - - fixed bug in reporting write protect (reported by Lyle Bickley) - - fixed TK70 model number and media ID (found by Robert Schaffrath) + pdp11_tq.c: + - fixed bug in reporting write protect (reported by Lyle Bickley) + - fixed TK70 model number and media ID (found by Robert Schaffrath) - pdp11_vh.c: added DHQ11 support (from John Dundas) + pdp11_vh.c: added DHQ11 support (from John Dundas) - pdp11_io.c, vax_io.c: fixed DHQ11 autoconfigure (from John Dundas) + pdp11_io.c, vax_io.c: fixed DHQ11 autoconfigure (from John Dundas) - pdp11_sys.c, vax_sys.c: added DHQ11 support (from John Dundas) + pdp11_sys.c, vax_sys.c: added DHQ11 support (from John Dundas) - vax_cpu.c: fixed bug in DIVBx, DIVWx (reported by Peter Trimmel) + vax_cpu.c: fixed bug in DIVBx, DIVWx (reported by Peter Trimmel) - 0 04-Apr-04 scp.c: - - added sim_vm_parse_addr and sim_vm_fprint_addr - - added REG_VMAD - - moved console logging to SCP - - changed sim_fsize to use descriptor rather than name - - added global device/unit show modifiers - - added device debug support (Dave Hittner) - - moved device and unit flags, updated save format + 0 04-Apr-04 scp.c: + - added sim_vm_parse_addr and sim_vm_fprint_addr + - added REG_VMAD + - moved console logging to SCP + - changed sim_fsize to use descriptor rather than name + - added global device/unit show modifiers + - added device debug support (Dave Hittner) + - moved device and unit flags, updated save format - sim_ether.c: - - further generalizations (Dave Hittner, Mark Pizzolato) + sim_ether.c: + - further generalizations (Dave Hittner, Mark Pizzolato) - sim_tmxr.h, sim_tmxr.c: - - added tmxr_linemsg - - changed TMXR definition to support variable number of lines + sim_tmxr.h, sim_tmxr.c: + - added tmxr_linemsg + - changed TMXR definition to support variable number of lines - sim_libraries: - - new console library (sim_console.h, sim_console.c) - - new file I/O library (sim_fio.h, sim_fio.c) - - new timer library (sim_timer.h, sim_timer.c) + sim_libraries: + - new console library (sim_console.h, sim_console.c) + - new file I/O library (sim_fio.h, sim_fio.c) + - new timer library (sim_timer.h, sim_timer.c) - all terminal multiplexors: revised for tmxr library changes + all terminal multiplexors: revised for tmxr library changes - all DECtapes: - - added STOP_EOR to enable end-of-reel stop - - revised for device debug support + all DECtapes: + - added STOP_EOR to enable end-of-reel stop + - revised for device debug support - all variable-sized devices: revised for sim_fsize change + all variable-sized devices: revised for sim_fsize change - eclipse_cpu.c, nova_cpu.c: fixed device enable/disable support - (found by Bruce Ray) + eclipse_cpu.c, nova_cpu.c: fixed device enable/disable support + (found by Bruce Ray) - nova_defs.h, nova_sys.c, nova_qty.c: - - added QTY and ALM support (Bruce Ray) + nova_defs.h, nova_sys.c, nova_qty.c: + - added QTY and ALM support (Bruce Ray) - id32_cpu.c, id_dp.c: revised for device debug support + id32_cpu.c, id_dp.c: revised for device debug support - lgp: added LGP-30 [LGP-21] simulator + lgp: added LGP-30 [LGP-21] simulator - pdp1_sys.c: fixed bug in LOAD (found by Mark Crispin) + pdp1_sys.c: fixed bug in LOAD (found by Mark Crispin) - pdp10_mdfp.c: - - fixed bug in floating unpack - - fixed bug in FIXR (found by Philip Stone, fixed by Chris Smith) + pdp10_mdfp.c: + - fixed bug in floating unpack + - fixed bug in FIXR (found by Philip Stone, fixed by Chris Smith) - pdp11_dz.c: added per-line logging + pdp11_dz.c: added per-line logging - pdp11_rk.c: - - added formatting support - - added address increment inhibit support - - added transfer overrun detection + pdp11_rk.c: + - added formatting support + - added address increment inhibit support + - added transfer overrun detection - pdp11_hk.c, pdp11_rp.c: revised for device debug support + pdp11_hk.c, pdp11_rp.c: revised for device debug support - pdp11_rq.c: fixed bug in interrupt control (found by Tom Evans) + pdp11_rq.c: fixed bug in interrupt control (found by Tom Evans) - pdp11_ry.c: added VAX support + pdp11_ry.c: added VAX support - pdp11_tm.c, pdp11_tq.c, pdp11_ts.c: revised for device debug support + pdp11_tm.c, pdp11_tq.c, pdp11_ts.c: revised for device debug support - pdp11_xu.c: replaced stub with real implementation (Dave Hittner) + pdp11_xu.c: replaced stub with real implementation (Dave Hittner) - pdp18b_cpu.c: - - fixed bug in XVM g_mode implementation - - fixed bug in PDP-15 indexed address calculation - - fixed bug in PDP-15 autoindexed address calculation + pdp18b_cpu.c: + - fixed bug in XVM g_mode implementation + - fixed bug in PDP-15 indexed address calculation + - fixed bug in PDP-15 autoindexed address calculation - pdp18b_fpp.c: fixed bugs in instruction decode + pdp18b_fpp.c: fixed bugs in instruction decode - pdp18b_stddev.c: - - fixed clock response to CAF - - fixed bug in hardware read-in mode bootstrap + pdp18b_stddev.c: + - fixed clock response to CAF + - fixed bug in hardware read-in mode bootstrap - pdp18b_sys.c: fixed XVM instruction decoding errors + pdp18b_sys.c: fixed XVM instruction decoding errors - pdp18b_tt1.c: added support for 1-16 additional terminals + pdp18b_tt1.c: added support for 1-16 additional terminals - vax_moddef.h, vax_cpu.c, vax_sysdev.c: - - added extended physical memory support (Mark Pizzolato) - - added RXV21 support + vax_moddef.h, vax_cpu.c, vax_sysdev.c: + - added extended physical memory support (Mark Pizzolato) + - added RXV21 support - vax_cpu1.c: - - added PC read fault in EXTxV - - fixed PC write fault in INSV + vax_cpu1.c: + - added PC read fault in EXTxV + - fixed PC write fault in INSV /* V3.1 revision history - 0 29-Dec-03 sim_defs.h, scp.c: added output stall status + 0 29-Dec-03 sim_defs.h, scp.c: added output stall status - all console emulators: added output stall support + all console emulators: added output stall support - sim_ether.c (Dave Hittner, Mark Pizzolato, Anders Ahgren): - - added Alpha/VMS support - - added FreeBSD, Mac OS/X support - - added TUN/TAP support - - added DECnet duplicate address detection + sim_ether.c (Dave Hittner, Mark Pizzolato, Anders Ahgren): + - added Alpha/VMS support + - added FreeBSD, Mac OS/X support + - added TUN/TAP support + - added DECnet duplicate address detection - all memory buffered devices (fixed head disks, floppy disks): - - cleaned up buffer copy code + all memory buffered devices (fixed head disks, floppy disks): + - cleaned up buffer copy code - all DECtapes: - - fixed reverse checksum in read all - - added DECtape off reel message - - simplified timing + all DECtapes: + - fixed reverse checksum in read all + - added DECtape off reel message + - simplified timing - eclipse_cpu.c (Charles Owen): - - added floating point support - - added programmable interval timer support - - bug fixes + eclipse_cpu.c (Charles Owen): + - added floating point support + - added programmable interval timer support + - bug fixes - h316_cpu.c: - - added instruction history - - added DMA/DMC support - - added device ENABLE/DISABLE support - - change default to HSA option included + h316_cpu.c: + - added instruction history + - added DMA/DMC support + - added device ENABLE/DISABLE support + - change default to HSA option included - h316_dp.c: added moving head disk support + h316_dp.c: added moving head disk support - h316_fhd.c: added fixed head disk support + h316_fhd.c: added fixed head disk support - h316_mt.c: added magtape support + h316_mt.c: added magtape support - h316_sys.c: added new device support + h316_sys.c: added new device support - nova_dkp.c (Charles Owen): - - fixed bug in flag clear sequence - - added diagnostic mode support for disk sizing + nova_dkp.c (Charles Owen): + - fixed bug in flag clear sequence + - added diagnostic mode support for disk sizing -` nova_mt.c (Charles Owen): - - fixed bug, space operations return record count - - fixed bug, reset doesn't cancel rewind +` nova_mt.c (Charles Owen): + - fixed bug, space operations return record count + - fixed bug, reset doesn't cancel rewind - nova_sys.c: added floating point, timer support (from Charles Owen) + nova_sys.c: added floating point, timer support (from Charles Owen) - i1620_cpu.c: fixed bug in branch digit (found by Dave Babcock) + i1620_cpu.c: fixed bug in branch digit (found by Dave Babcock) - pdp1_drm.c: - - added parallel drum support - - fixed bug in serial drum instructin decoding + pdp1_drm.c: + - added parallel drum support + - fixed bug in serial drum instructin decoding - pdp1_sys.c: added parallel drum support, mnemonics + pdp1_sys.c: added parallel drum support, mnemonics - pdp11_cpu.c: - - added autoconfiguration controls - - added support for 18b-only Qbus devices - - cleaned up addressing/bus definitions + pdp11_cpu.c: + - added autoconfiguration controls + - added support for 18b-only Qbus devices + - cleaned up addressing/bus definitions - pdp11_rk.c, pdp11_ry.c, pdp11_tm.c, pdp11_hk.c: - - added Q18 attribute + pdp11_rk.c, pdp11_ry.c, pdp11_tm.c, pdp11_hk.c: + - added Q18 attribute - pdp11_io.c: - - added autoconfiguration controls - - fixed bug in I/O configuration (found by Dave Hittner) + pdp11_io.c: + - added autoconfiguration controls + - fixed bug in I/O configuration (found by Dave Hittner) - pdp11_rq.c: - - revised MB->LBN conversion for greater accuracy - - fixed bug with multiple RAUSER drives + pdp11_rq.c: + - revised MB->LBN conversion for greater accuracy + - fixed bug with multiple RAUSER drives - pdp11_tc.c: changed to be off by default (base config is Qbus) + pdp11_tc.c: changed to be off by default (base config is Qbus) - pdp11_xq.c (Dave Hittner, Mark Pizzolato): - - fixed second controller interrupts - - fixed bugs in multicast and promiscuous setup + pdp11_xq.c (Dave Hittner, Mark Pizzolato): + - fixed second controller interrupts + - fixed bugs in multicast and promiscuous setup - pdp18b_cpu.c: - - added instruction history - - fixed PDP-4,-7,-9 autoincrement bug - - change PDP-7,-9 default to API option included + pdp18b_cpu.c: + - added instruction history + - fixed PDP-4,-7,-9 autoincrement bug + - change PDP-7,-9 default to API option included - pdp8_defs.h, pdp8_sys.c: - - added DECtape off reel message - - added support for TSC8-75 (ETOS) option - - added support for TD8E controller + pdp8_defs.h, pdp8_sys.c: + - added DECtape off reel message + - added support for TSC8-75 (ETOS) option + - added support for TD8E controller - pdp8_cpu.c: added instruction history + pdp8_cpu.c: added instruction history - pdp8_rx.c: - - fixed bug in RX28 read status (found by Charles Dickman) - - fixed double density write + pdp8_rx.c: + - fixed bug in RX28 read status (found by Charles Dickman) + - fixed double density write - pdp8_td.c: added TD8E controller + pdp8_td.c: added TD8E controller - pdp8_tsc.c: added TSC8-75 option + pdp8_tsc.c: added TSC8-75 option - vax_cpu.c: - - revised instruction history for dynamic sizing - - added autoconfiguration controls + vax_cpu.c: + - revised instruction history for dynamic sizing + - added autoconfiguration controls - vax_io.c: - - added autoconfiguration controls - - fixed bug in I/O configuration (found by Dave Hittner) + vax_io.c: + - added autoconfiguration controls + - fixed bug in I/O configuration (found by Dave Hittner) - id16_cpu.c: revised instruction decoding + id16_cpu.c: revised instruction decoding - id32_cpu.c: - - revised instruction decoding - - added instruction history + id32_cpu.c: + - revised instruction decoding + - added instruction history /* V3.0 revision history - 2 15-Sep-03 scp.c: - - fixed end-of-file problem in dep, idep - - fixed error on trailing spaces in dep, idep + 2 15-Sep-03 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_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 + 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 + 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) + 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) + 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 + 1 27-Jul-03 pdp1_cpu.c: updated to detect indefinite I/O wait - pdp1_drm.c: fixed incorrect logical, missing activate, break + 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_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_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 + pdp1_sys.c: added block loader format support to LOAD - pdp10_rp.c: fixed bug in read header + pdp10_rp.c: fixed bug in read header - pdp11_rq: fixed bug in user disk size (found by Chaskiel M Grundman) + 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_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_fpp.c: added FP15 - pdp18b_lp.c: fixed bug in Type 62 overprinting + pdp18b_lp.c: fixed bug in Type 62 overprinting - pdp18b_rf.c: fixed bug in set size routine + 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_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 + pdp18b_sys.c: added FP15, KT15, XVM instructions - pdp8b_df.c, pdp8_rf.c: fixed bug in set size routine + 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 + hp2100_dr.c: + - fixed drum sizes + - fixed variable capacity interaction with SAVE/RESTORE - i1401_cpu.c: revised fetch to model hardware more closely + i1401_cpu.c: revised fetch to model hardware more closely - ibm1130: fixed bugs found by APL 1130 + ibm1130: fixed bugs found by APL 1130 - nova_dsk.c: fixed bug in set size routine + nova_dsk.c: fixed bug in set size routine - altairz80: fixed bug in real-time clock on Windows host + 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 + 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 + scp_tty.c: added extended file seek - sim_sock.c: fixed calling sequence in stubs + sim_sock.c: fixed calling sequence in stubs - sim_tape.c: - - added E11 and TPC format support - - added extended file support + sim_tape.c: + - added E11 and TPC format support + - added extended file support - sim_tmxr.c: fixed bug in SHOW CONNECTIONS + sim_tmxr.c: fixed bug in SHOW CONNECTIONS - all magtapes: - - added multiformat support - - added extended file support + 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_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 + i1401_mt.c: fixed load-mode end of record response - nova_dsk.c: fixed variable size interaction with restore + nova_dsk.c: fixed variable size interaction with restore - pdp1_dt.c: fixed variable size interaction with restore + pdp1_dt.c: fixed variable size interaction with restore - pdp10_rp.c: fixed ordering bug in attach + 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_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_lp.c, pdp11_rq.c: added extended file support - pdp11_rl.c, pdp11_rp.c, pdp11_ry.c: fixed ordering bug in attach + pdp11_rl.c, pdp11_rp.c, pdp11_ry.c: fixed ordering bug in attach - pdp11_tc.c: fixed variable size interaction with restore + 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 + 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_fpa.c: + - fixed integer overflow bug in CVTfi + - fixed multiple bugs in EMODf - vax_io.c: optimized byte and word DMA routines + 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) + 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 + pdp1_dt.c: fixed variable size interaction with restore - pdp18b_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_mt.c: fixed bug in MTTR - pdp18b_rf.c: fixed variable size interaction with restore + pdp18b_rf.c: fixed variable size interaction with restore - pdp8_df.c, pdp8_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_dt.c: fixed variable size interaction with restore - pdp8_mt.c: fixed bug in SKTR + 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 + 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) + id_pt.c: fixed type declaration (found by Mark Pizzolato) - gri_cpu.c: fixed bug in SC queue pointer management + 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 + 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 + sim_tape.c: magtape simulation library - h316_stddev.c: added set line frequency command + h316_stddev.c: added set line frequency command - hp2100_mt.c, hp2100_ms.c: revised to use magtape library + hp2100_mt.c, hp2100_ms.c: revised to use magtape library - i1401_mt.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_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 + 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 + 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 + 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_clk.c: added set line frequency command - nova_dsk.c: fixed autosizing algorithm + nova_dsk.c: fixed autosizing algorithm - nova_mt.c: revised to use magtape library + nova_mt.c: revised to use magtape library - pdp10_tu.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_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_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_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_ry.c: fixed autosizing algorithm - pdp11_tm.c, pdp11_ts.c: revised to use magtape library + 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 + 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_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_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_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_stddev.c: + - added set line frequency command + - added set ctrl-c command - pdp18b_sys.c: fixed FMTASC printouts (found by Hans Pufal) + pdp18b_sys.c: fixed FMTASC printouts (found by Hans Pufal) - pdp8_clk.c: added set line frequency command + pdp8_clk.c: added set line frequency command - pdp8_df.c, pdp8_rf.c, pdp8_rx.c: fixed autosizing algorithm + 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_mt.c: + - fixed bug in BOT error handling + - revised to use magtape library - pdp8_tt.c: added set ctrl-c command + pdp8_tt.c: added set ctrl-c command - sds_cpu.c: added set line frequency command + sds_cpu.c: added set line frequency command - sds_mt.c: revised to use magtape library + sds_mt.c: revised to use magtape library - vax_stddev.c: added set ctrl-c command + vax_stddev.c: added set ctrl-c command - 3 06-Feb-03 scp.c: - - added dynamic extension of the breakpoint table - - added breakpoint actions + 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_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) + hp2100_ipl.c: individual links are full duplex (found by + Mike Gemeny) - pdp11_cpu.c: changed R, SP to track PSW respectively + pdp11_cpu.c: changed R, SP to track PSW respectively - pdp18b_defs.h, pdp18b_sys.c: added RB09 fixed head disk, - LP09 printer + 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 (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_rf.c: + - fixed IOT decoding + - fixed bug in command initiation - pdp18b_rb.c: new RB09 fixed head disk + pdp18b_rb.c: new RB09 fixed head disk - pdp18b_lp.c: new LP09 line printer + pdp18b_lp.c: new LP09 line printer - pdp8_df.c: added variable number of platters and autosizing + pdp8_df.c: added variable number of platters and autosizing - pdp8_rf.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 + nova_dsk.c: added variable number of platters and autosizing - id16_cpu.c: fixed bug in SETM, SETMR (found by Mark Pizzolato) + 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) + 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_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 + 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 + 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 + pdp18_defs.h: added PDP-4 drum support - hp2100_cpu.c: added 21MX IOP 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 + 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) + 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 + 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_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 + 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) + 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) + pdp18b_stddev.c: added "ASCII mode" for reader and + punch (from Hans Pufal) - gri_*.c: added GRI-909 simulator + gri_*.c: added GRI-909 simulator - scp.c: added DO echo, DO exit (from Brian Knittel) + scp.c: added DO echo, DO exit (from Brian Knittel) - scp_tty.c: added Windows priority hacking (from - Mark Pizzolato) + 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) + 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) + 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) + 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 + 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_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 + i1401_dp.c: added 1311 disk - 9 04-May-02 pdp11_rq: fixed bug in polling routine + 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 + 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 + 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_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 + 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) + 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_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 + pdp11_rp.c: fixed SHOW ADDRESS command - vaxmod_defs.h: fixed DZ vector base and number of lines + vaxmod_defs.h: fixed DZ vector base and number of lines - dec_dz.h: - - fixed interrupt acknowledge routines - - fixed SHOW ADDRESS command + 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) + 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 + 6 18-Apr-02 vax_cpu.c: fixed CASEL condition codes - vax_cpu1.c: fixed vfield pos > 31 test to be unsigned + vax_cpu1.c: fixed vfield pos > 31 test to be unsigned - vax_fpu.c: fixed EDIV overflow test for 0 quotient + 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) + 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 + 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 + 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) + 3 15-Mar-02 pdp11_defs.h: changed default model to KDJ11A (11/73) - pdp11_rq.c: adjusted delays for M+ timing bugs + 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, 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 + 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+ + 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 + 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 + 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_rq.c: fixed bug in host timeout logic - pdp11_ts.c: fixed bug in message header logic + pdp11_ts.c: fixed bug in message header logic - pdp18b_defs.h, pdp18b_dt.c, pdp18b_sys.c: added - PDP-7 DECtape support + 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_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_sys.c: added floating point, DMS - hp2100_fp.c: added floating point + hp2100_fp.c: added floating point - ibm1130: added Brian Knittel's IBM 1130 simulator + 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 + 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) + 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_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) + 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 + 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_defs.h: fixed bug in interrupt enable initialization - pdp8_ttx.c: rewrote as unified multiplexor + pdp8_ttx.c: rewrote as unified multiplexor - pdp11_cpu.c: fixed calc_MMR1 macro (found by Robert Alan Byer) + pdp11_cpu.c: fixed calc_MMR1 macro (found by Robert Alan Byer) - pdp11_stddev.c: fixed bugs in KW11L (found by John Dundas) + pdp11_stddev.c: fixed bugs in KW11L (found by John Dundas) - pdp11_rp.c: fixed bug in 18b mode boot + pdp11_rp.c: fixed bug in 18b mode boot - pdp11 bootable I/O devices: fixed register setup at boot - exit (found by Doug Carman) + 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_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_mt.c: fixed bug on write of last character - hp2100_dq,dr,ms,mux.c: added new disk, magtape, and terminal - multiplexor controllers + 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_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) + 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 + 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) +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 + 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_cpu.c: cleaned up declarations - pdp11_rq.c: added RA-class disks + pdp11_rq.c: added RA-class disks -4 17-Dec-01 pdp11_rq.c: added delayed processing of packets +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 +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 +2 07-Dec-01 scp.c: added breakpoint package - all CPU's: revised to use new breakpoint package + all CPU's: revised to use new breakpoint package -1 05-Dec-01 scp.c: fixed bug in universal register name logic +1 05-Dec-01 scp.c: fixed bug in universal register name logic -0 30-Nov-01 Reorganized simh source and documentation tree +0 30-Nov-01 Reorganized simh source and documentation tree - scp: Added DO command, universal registers, extended - SET/SHOW logic + 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 + pdp11: overhauled PDP-11 for DMA map support, shared + sources with VAX, dynamic buffer allocation - 18b pdp: overhauled interrupt structure + 18b pdp: overhauled interrupt structure - pdp8: added RL8A + pdp8: added RL8A - pdp10: fixed two ITS-related bugs (found by Dave Conroy) + pdp10: fixed two ITS-related bugs (found by Dave Conroy) V2.7 revision history -patch date module(s) and fix(es) +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 +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 + 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 +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) +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 +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 +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 + 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 +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 +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 + 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 +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 +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 +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 + 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 +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 +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 + 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 + 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 + scp.c: + - added routine sim_qcount for 1130 + - added "simulator exit" detach routine for 1130 - sim_defs.h: added header for sim_qcount + sim_defs.h: added header for sim_qcount -3 20-Sep-01 pdp11_ts.c: boot code binary was incorrect +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 +2 19-Sep-01 pdp18b_cpu.c: EAE should interpret initial count of 00 + as 100 - scp.c: modified Macintosh support + scp.c: modified Macintosh support -1 17-Sep-01 pdp8_ttx.c: new module for PDP-8 multi-terminal 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 + pdp18b_tt1.c: modified to use sim_tmxr library - nova_tt1.c: modified to use sim_tmxr library + nova_tt1.c: modified to use sim_tmxr library - dec_dz.h: added autodisconnect support + dec_dz.h: added autodisconnect support - scp.c: removed old multiconsole support + scp.c: removed old multiconsole support - sim_tmxr.c: modified calling sequence for sim_putchar_ln + sim_tmxr.c: modified calling sequence for sim_putchar_ln - sim_sock.c: added Macintosh sockets support + sim_sock.c: added Macintosh sockets support */ #endif diff --git a/sim_sock.c b/sim_sock.c index bec90cc9..63de4067 100644 --- a/sim_sock.c +++ b/sim_sock.c @@ -19,21 +19,22 @@ 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 + 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. - 14-Apr-05 RMS Added WSAEINPROGRESS test (from Tim Riker) - 09-Jan-04 RMS Fixed typing problem in Alpha Unix (found by Tim Chapman) - 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 + 16-Aug-05 RMS Fixed spurious SIGPIPE signal error in Unix + 14-Apr-05 RMS Added WSAEINPROGRESS test (from Tim Riker) + 09-Jan-04 RMS Fixed typing problem in Alpha Unix (found by Tim Chapman) + 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" @@ -42,15 +43,15 @@ /* 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 + 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 */ @@ -92,8 +93,8 @@ SOCKET sim_setnonblock (SOCKET sock) return SOCKET_ERROR; } -#else /* endif unimpl */ - +#else /* endif unimpl */ + /* UNIX, Win32, Macintosh, VMS, OS2 (Berkeley socket) routines */ SOCKET sim_err_sock (SOCKET s, char *emsg, int32 flg) @@ -116,18 +117,24 @@ 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; } } + 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 */ +#endif /* endif Win32 */ +#if defined (SIGPIPE) +signal (SIGPIPE, SIG_IGN); /* no pipe signals */ +#endif -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; } +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; } @@ -137,23 +144,23 @@ SOCKET newsock; struct sockaddr_in name; int32 sta; -newsock = sim_create_sock (); /* create socket */ -if (newsock == INVALID_SOCKET) return newsock; /* socket error? */ +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 */ +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! */ +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) @@ -162,31 +169,31 @@ SOCKET newsock; struct sockaddr_in name; int32 sta; -newsock = sim_create_sock (); /* create socket */ -if (newsock == INVALID_SOCKET) return newsock; /* socket error? */ +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 */ +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 = 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) && (WSAGetLastError () != WSAEINPROGRESS)) - return sim_err_sock (newsock, "connect", 1); + return sim_err_sock (newsock, "connect", 1); -return newsock; /* got it! */ +return newsock; /* got it! */ } SOCKET sim_accept_conn (SOCKET master, uint32 *ipaddr) { int32 sta, err; -#if defined (macintosh) +#if defined (macintosh) || defined (__linux) || defined (__APPLE__) socklen_t size; -#elif defined (_WIN32) || defined (__EMX__) || defined (__APPLE__) ||\ +#elif defined (_WIN32) || defined (__EMX__) ||\ (defined (__ALPHA) && defined (__unix__)) int size; #else @@ -195,19 +202,20 @@ size_t size; SOCKET newsock; struct sockaddr_in clientname; -if (master == 0) return INVALID_SOCKET; /* not attached? */ +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 (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); +sta = sim_setnonblock (newsock); /* set nonblocking */ +if (sta == SOCKET_ERROR) /* fcntl error? */ + return sim_err_sock (newsock, "fcntl", 0); return newsock; } @@ -235,12 +243,13 @@ 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 == 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; } + err = WSAGetLastError (); + if (err == WSAEWOULDBLOCK) return 0; /* no data */ + printf ("Sockets: read error %d\n", err); + return -1; + } return rbytes; } @@ -254,48 +263,50 @@ 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; } } + 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 */ +#if defined (_WIN32) /* Windows */ SOCKET sim_setnonblock (SOCKET sock) { unsigned long non_block = 1; -return ioctlsocket (sock, FIONBIO, &non_block); /* set nonblocking */ +return ioctlsocket (sock, FIONBIO, &non_block); /* set nonblocking */ } -#elif defined (VMS) /* VMS */ +#elif defined (VMS) /* VMS */ SOCKET sim_setnonblock (SOCKET sock) { int non_block = 1; -return ioctl (sock, FIONBIO, &non_block); /* set nonblocking */ +return ioctl (sock, FIONBIO, &non_block); /* set nonblocking */ } -#else /* Mac, Unix, OS/2 */ +#else /* Mac, Unix, OS/2 */ int32 sim_setnonblock (SOCKET sock) { int32 fl, sta; -fl = fcntl (sock, F_GETFL,0); /* get flags */ +fl = fcntl (sock, F_GETFL,0); /* get flags */ if (fl == -1) return SOCKET_ERROR; -sta = fcntl (sock, F_SETFL, fl | O_NONBLOCK); /* set nonblock */ +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 !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 /* endif !Win32 && !VMS */ -#endif /* end else !implemented */ +#endif /* end else !implemented */ diff --git a/sim_sock.h b/sim_sock.h index 66954b49..fd38f516 100644 --- a/sim_sock.h +++ b/sim_sock.h @@ -19,58 +19,58 @@ 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 + 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. - 14-Apr-05 RMS Added WSAEINPROGRESS (from Tim Riker) - 20-Aug-04 HV Added missing definition for OS/2 (from Holger Veit) + 14-Apr-05 RMS Added WSAEINPROGRESS (from Tim Riker) + 20-Aug-04 HV Added missing definition for OS/2 (from Holger Veit) 22-Oct-03 MP Changed WIN32 winsock include to use winsock2.h to avoid a conflict if sim_sock.h and sim_ether.h get included by the same module. - 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 + 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 +#define _SIM_SOCK_H_ 0 -#if defined (_WIN32) /* Windows */ -#undef INT_PTR /* hack, hack */ +#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 WSAEINPROGRESS EINPROGRESS -#define INVALID_SOCKET -1 -#define SOCKET_ERROR -1 -#include /* for fcntl, getpid */ -#include /* for sockets */ +#elif !defined (__OS2__) || defined (__EMX__) /* VMS, Mac, Unix, OS/2 EMX */ +#define WSAGetLastError() errno /* Windows macros */ +#define SOCKET int32 +#define WSAEWOULDBLOCK EWOULDBLOCK +#define WSAEINPROGRESS EINPROGRESS +#define INVALID_SOCKET -1 +#define SOCKET_ERROR -1 +#include /* for fcntl, getpid */ +#include /* for sockets */ #include #include -#include /* for sockaddr_in */ +#include /* for sockaddr_in */ #include -#include /* for EMX */ +#include /* for EMX */ #endif -#if defined (VMS) /* VMS unique */ -#include /* for ioctl */ +#if defined (VMS) /* VMS unique */ +#include /* for ioctl */ #if !defined (timerclear) #define timerclear(tvp) (tvp)->tv_sec = (tvp)->tv_usec = 0 #endif #endif -#if defined(__EMX__) /* OS/2 unique */ +#if defined(__EMX__) /* OS/2 unique */ #if !defined (timerclear) -#define timerclear(tvp) (tvp)->tv_sec = (tvp)->tv_usec = 0 +#define timerclear(tvp) (tvp)->tv_sec = (tvp)->tv_usec = 0 #endif #endif diff --git a/sim_tape.c b/sim_tape.c index b7c270d7..4eb27a27 100644 --- a/sim_tape.c +++ b/sim_tape.c @@ -1,6 +1,6 @@ /* sim_tape.c: simulator tape support library - Copyright (c) 1993-2004, Robert M Supnik + Copyright (c) 1993-2005, 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"), @@ -19,55 +19,58 @@ 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 + 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. - 28-Jul-04 RMS Fixed bug in writing error records (found by Dave Bryan) - RMS Fixed incorrect error codes (found by Dave Bryan) - 05-Jan-04 RMS Revised for file I/O library - 25-Apr-03 RMS Added extended file support - 28-Mar-03 RMS Added E11 and TPC format support + 16-Aug-05 RMS Fixed C++ declaration and cast problems + 02-May-05 RMS Added support for Pierce 7b format + 28-Jul-04 RMS Fixed bug in writing error records (found by Dave Bryan) + RMS Fixed incorrect error codes (found by Dave Bryan) + 05-Jan-04 RMS Revised for file I/O library + 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 + 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 */ -}; + 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 } -}; + { "SIMH", 0, sizeof (t_mtrlnt) - 1 }, + { "E11", 0, sizeof (t_mtrlnt) - 1 }, + { "TPC", UNIT_RO, sizeof (t_tpclnt) - 1 }, + { "P7B", UNIT_RO, 0 }, +/* { "TPF", UNIT_RO, 0 }, */ + { NULL, 0, 0 } + }; extern int32 sim_switches; @@ -84,29 +87,34 @@ 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? */ +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 */ -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; } + 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_addr)); + 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, (t_addr *) uptr->filebuf); /* fill map */ + break; + + default: + break; + } sim_tape_rewind (uptr); return SCPE_OK; @@ -119,17 +127,19 @@ t_stat sim_tape_detach (UNIT *uptr) uint32 f = MT_GET_FMT (uptr); t_stat r; -r = detach_unit (uptr); /* detach unit */ +r = detach_unit (uptr); /* detach unit */ if (r != SCPE_OK) return r; +switch (f) { /* case on format */ -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; } + 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; @@ -138,62 +148,89 @@ return SCPE_OK; /* Read record length forward (internal routine) Inputs: - uptr = pointer to tape unit - bc = pointer to returned record length + uptr = pointer to tape unit + bc = pointer to returned record length Outputs: - status = operation status + status = operation status - exit condition position + exit condition position - unit unattached unchanged - read error unchanged, PNU set - end of file/medium unchanged, PNU set - tape mark updated - data record updated, sim_fread will read record forward + unit unattached unchanged + read error unchanged, PNU set + end of file/medium unchanged, PNU set + tape mark updated + data record updated, sim_fread will read record forward */ t_stat sim_tape_rdlntf (UNIT *uptr, t_mtrlnt *bc) { +uint8 c; +t_bool all_eof; 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? */ -sim_fseek (uptr->fileref, uptr->pos, SEEK_SET); /* set tape pos */ +if ((uptr->flags & UNIT_ATT) == 0) return MTSE_UNATT; /* not attached? */ +sim_fseek (uptr->fileref, uptr->pos, SEEK_SET); /* set tape pos */ +switch (f) { /* switch on fmt */ -switch (f) { /* switch on fmt */ -case MTUF_F_STD: case MTUF_F_E11: - sim_fread (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_STD: case MTUF_F_E11: + sim_fread (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: - sim_fread (&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; + case MTUF_F_TPC: + sim_fread (&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; } + case MTUF_F_P7B: + for (sbc = 0, all_eof = 1; ; sbc++) { /* loop thru record */ + sim_fread (&c, sizeof (uint8), 1, uptr->fileref); + if (ferror (uptr->fileref)) { /* error? */ + MT_SET_PNU (uptr); /* pos not upd */ + return sim_tape_ioerr (uptr); + } + if (feof (uptr->fileref)) { /* eof? */ + if (sbc == 0) return MTSE_EOM; /* no data? eom */ + break; /* treat like eor */ + } + if ((sbc != 0) && (c & P7B_SOR)) break; /* next record? */ + if ((c & P7B_DATA) != P7B_EOF) all_eof = 0; + } + *bc = sbc; /* save rec lnt */ + sim_fseek (uptr->fileref, uptr->pos, SEEK_SET); /* for read */ + uptr->pos = uptr->pos + sbc; /* spc over record */ + if (all_eof) return MTSE_TMK; /* tape mark? */ + break; + + default: + return MTSE_FMT; + } return MTSE_OK; } @@ -201,161 +238,187 @@ return MTSE_OK; /* Read record length reverse (internal routine) Inputs: - uptr = pointer to tape unit - bc = pointer to returned record length + uptr = pointer to tape unit + bc = pointer to returned record length Outputs: - status = operation status + status = operation status - exit condition position + 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, sim_fread will read record forward + unit unattached unchanged + beginning of tape unchanged + read error unchanged + end of file unchanged + end of medium updated + tape mark updated + data record updated, sim_fread will read record forward */ t_stat sim_tape_rdlntr (UNIT *uptr, t_mtrlnt *bc) { +uint8 c; +t_bool all_eof; 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? */ +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 */ -switch (f) { /* switch on fmt */ -case MTUF_F_STD: case MTUF_F_E11: - sim_fseek (uptr->fileref, uptr->pos - sizeof (t_mtrlnt), SEEK_SET); - sim_fread (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); - sim_fseek (uptr->fileref, uptr->pos + sizeof (t_mtrlnt), SEEK_SET); - break; + case MTUF_F_STD: case MTUF_F_E11: + sim_fseek (uptr->fileref, uptr->pos - sizeof (t_mtrlnt), SEEK_SET); + sim_fread (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); + sim_fseek (uptr->fileref, uptr->pos + sizeof (t_mtrlnt), SEEK_SET); + break; + + case MTUF_F_TPC: + ppos = sim_tape_tpc_fnd (uptr, (t_addr *) uptr->filebuf); /* find prev rec */ + sim_fseek (uptr->fileref, ppos, SEEK_SET); /* position */ + sim_fread (&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? */ + sim_fseek (uptr->fileref, uptr->pos + sizeof (t_tpclnt), SEEK_SET); + break; + + case MTUF_F_P7B: + for (sbc = 1, all_eof = 1; ; sbc++) { /* loop thru record */ + sim_fseek (uptr->fileref, uptr->pos - sbc, SEEK_SET); + sim_fread (&c, sizeof (uint8), 1, uptr->fileref); + if (ferror (uptr->fileref)) /* error? */ + return sim_tape_ioerr (uptr); + if (feof (uptr->fileref)) return MTSE_EOM; /* eof? */ + if ((c & P7B_DATA) != P7B_EOF) all_eof = 0; + if (c & P7B_SOR) break; /* start of record? */ + } + uptr->pos = uptr->pos - sbc; /* update position */ + sim_fseek (uptr->fileref, uptr->pos, SEEK_SET); /* for read */ + if (all_eof) return MTSE_TMK; /* tape mark? */ + break; + + default: + return MTSE_FMT; + } -case MTUF_F_TPC: - ppos = sim_tape_tpc_fnd (uptr, uptr->filebuf); /* find prev rec */ - sim_fseek (uptr->fileref, ppos, SEEK_SET); /* position */ - sim_fread (&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? */ - sim_fseek (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 + uptr = pointer to tape unit + buf = pointer to buffer + bc = pointer to returned record length + max = maximum record size Outputs: - status = operation status + status = operation status - exit condition position + 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 + 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) { +uint32 f = MT_GET_FMT (uptr); 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 = sim_fread (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 */ +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 = sim_fread (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 */ +if (f == MTUF_F_P7B) buf[0] = buf[0] & P7B_DPAR; /* p7b? strip SOR */ 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 + uptr = pointer to tape unit + buf = pointer to buffer + bc = pointer to returned record length + max = maximum record size Outputs: - status = operation status + status = operation status - exit condition position + 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 + 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) { +uint32 f = MT_GET_FMT (uptr); 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 = sim_fread (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 */ +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 = sim_fread (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 */ +if (f == MTUF_F_P7B) buf[0] = buf[0] & P7B_DPAR; /* p7b? strip SOR */ return (MTR_F (tbc)? MTSE_RECE: MTSE_OK); } /* Write record forward Inputs: - uptr = pointer to tape unit - buf = pointer to buffer - bc = record length + uptr = pointer to tape unit + buf = pointer to buffer + bc = record length Outputs: - status = operation status + status = operation status - exit condition position + exit condition position - unit unattached unchanged - write protect unchanged - write error unchanged, PNU set - data record updated + 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) @@ -364,18 +427,19 @@ uint32 f = MT_GET_FMT (uptr); t_mtrlnt sbc; MT_CLR_PNU (uptr); -if ((uptr->flags & UNIT_ATT) == 0) return MTSE_UNATT; /* not attached? */ -if (sim_tape_wrp (uptr)) return MTSE_WRP; /* write prot? */ +if ((uptr->flags & UNIT_ATT) == 0) return MTSE_UNATT; /* not attached? */ +if (sim_tape_wrp (uptr)) return MTSE_WRP; /* write prot? */ if (f == MTUF_F_STD) sbc = MTR_L ((bc + 1) & ~1); else sbc = MTR_L (bc); -sim_fseek (uptr->fileref, uptr->pos, SEEK_SET); /* set pos */ +sim_fseek (uptr->fileref, uptr->pos, SEEK_SET); /* set pos */ sim_fwrite (&bc, sizeof (t_mtrlnt), 1, uptr->fileref); sim_fwrite (buf, sizeof (uint8), sbc, uptr->fileref); sim_fwrite (&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 */ +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; } @@ -384,14 +448,15 @@ return MTSE_OK; 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 (sim_tape_wrp (uptr)) return MTSE_WRP; /* write prot? */ -sim_fseek (uptr->fileref, uptr->pos, SEEK_SET); /* set pos */ +if ((uptr->flags & UNIT_ATT) == 0) return MTSE_UNATT; /* not attached? */ +if (sim_tape_wrp (uptr)) return MTSE_WRP; /* write prot? */ +sim_fseek (uptr->fileref, uptr->pos, SEEK_SET); /* set pos */ sim_fwrite (&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 */ +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; } @@ -415,7 +480,7 @@ t_stat sim_tape_sprecf (UNIT *uptr, t_mtrlnt *bc) { t_stat st; -st = sim_tape_rdlntf (uptr, bc); /* get record length */ +st = sim_tape_rdlntf (uptr, bc); /* get record length */ *bc = MTR_L (*bc); return st; } @@ -427,10 +492,11 @@ 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 MTSE_OK; } -st = sim_tape_rdlntr (uptr, bc); /* get record length */ + MT_CLR_PNU (uptr); + *bc = 0; + return MTSE_OK; + } +st = sim_tape_rdlntr (uptr, bc); /* get record length */ *bc = MTR_L (*bc); return st; } @@ -493,10 +559,12 @@ 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; } } + 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; } @@ -521,12 +589,13 @@ uint32 i, objc; if ((uptr == NULL) || (uptr->fileref == NULL)) return 0; for (objc = 0, tpos = 0;; ) { - sim_fseek (uptr->fileref, tpos, SEEK_SET); - i = sim_fread (&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); } + sim_fseek (uptr->fileref, tpos, SEEK_SET); + i = sim_fread (&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; } @@ -541,11 +610,13 @@ 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; } +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 index 536552a0..3003ab56 100644 --- a/sim_tape.h +++ b/sim_tape.h @@ -1,6 +1,6 @@ /* sim_tape.h: simulator tape support library definitions - Copyright (c) 1993-2004, Robert M Supnik + Copyright (c) 1993-2005, 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"), @@ -19,65 +19,75 @@ 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 + 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. + + 02-May-05 RMS Added support for Paul Pierce 7b format */ #ifndef _SIM_TAPE_H_ -#define _SIM_TAPE_H_ 0 +#define _SIM_TAPE_H_ 0 /* SIMH/E11 tape format */ -typedef uint32 t_mtrlnt; /* magtape rec lnt */ +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 */ +#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 */ +typedef uint16 t_tpclnt; /* magtape rec lnt */ -#define TPC_TMK 0x0000 /* tape mark */ +/* P7B tape format */ + +#define P7B_SOR 0x80 /* start of record */ +#define P7B_DPAR 0x7F /* data and parity */ +#define P7B_DATA 0x3F /* data */ +#define P7B_EOF 0x0F /* eof character */ + +#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 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 MTUF_F_P7B 3 /* P7B format */ +#define MUTF_F_TDF 4 /* 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) +#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 */ +#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 */ diff --git a/sim_timer.c b/sim_timer.c index c971afe5..e136de4c 100644 --- a/sim_timer.c +++ b/sim_timer.c @@ -1,6 +1,6 @@ /* sim_timer.c: simulator timer library - Copyright (c) 1993-2004, Robert M Supnik + Copyright (c) 1993-2005, 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"), @@ -19,95 +19,26 @@ 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 + 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. - 02-Jan-04 RMS Split out from SCP + 21-Aug-05 RMS Added sim_rtcn_init_all + 16-Aug-05 RMS Fixed C++ declaration and cast problems + 02-Jan-04 RMS Split out from SCP This library includes the following routines: - sim_rtc_init - initialize calibration - sim_rtc_calb - calibrate clock - sim_os_msec - return elapsed time in msec - sim_os_sleep - sleep specified number of seconds + sim_rtc_init - initialize calibration + sim_rtc_calb - calibrate clock + sim_os_msec - return elapsed time in msec + sim_os_sleep - sleep specified number of seconds The calibration routines are OS-independent; the _os_ routines are not */ #include "sim_defs.h" - -/* OS independent clock calibration package */ -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 */ -static int32 rtc_initd[SIM_NTIMERS] = { 0 }; /* initial delay */ -const 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; -rtc_initd[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 */ -rtc_vtime[tmr] = rtc_vtime[tmr] + 1000; /* adv sim time */ -if (delta_rtime > 30000) /* gap too big? */ - return rtc_initd[tmr]; /* can't calibr */ -if (delta_rtime == 0) /* gap too small? */ - rtc_based[tmr] = rtc_based[tmr] * ticksper; /* slew wide */ -else rtc_based[tmr] = (int32) (((double) rtc_based[tmr] * (double) rtc_nxintv[tmr]) / - ((double) delta_rtime)); /* new base rate */ -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_based[tmr] <= 0) rtc_based[tmr] = 1; /* never negative or zero! */ -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); -} - /* OS-dependent timer and clock routines */ /* VMS */ @@ -128,7 +59,7 @@ uint32 sim_os_msec () uint32 quo, htod, tod[2]; int32 i; -sys$gettim (tod); /* time 0.1usec */ +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 @@ -136,14 +67,16 @@ sys$gettim (tod); /* time 0.1usec */ */ 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 */ +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; } @@ -245,3 +178,74 @@ return; } #endif + +/* OS independent clock calibration package */ + +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 */ +static int32 rtc_initd[SIM_NTIMERS] = { 0 }; /* initial delay */ + +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; +rtc_initd[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 */ +rtc_vtime[tmr] = rtc_vtime[tmr] + 1000; /* adv sim time */ +if (delta_rtime > 30000) /* gap too big? */ + return rtc_initd[tmr]; /* can't calibr */ +if (delta_rtime == 0) /* gap too small? */ + rtc_based[tmr] = rtc_based[tmr] * ticksper; /* slew wide */ +else rtc_based[tmr] = (int32) (((double) rtc_based[tmr] * (double) rtc_nxintv[tmr]) / + ((double) delta_rtime)); /* new base rate */ +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_based[tmr] <= 0) rtc_based[tmr] = 1; /* never negative or zero! */ +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); +} diff --git a/sim_timer.h b/sim_timer.h index 6c3a390e..580c700a 100644 --- a/sim_timer.h +++ b/sim_timer.h @@ -1,6 +1,6 @@ /* sim_timer.h: simulator timer library headers - Copyright (c) 1993-2004, Robert M Supnik + Copyright (c) 1993-2005, 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"), @@ -19,18 +19,18 @@ 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 + 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. - 02-Jan-04 RMS Split out from SCP + 02-Jan-04 RMS Split out from SCP */ #ifndef _SIM_TIMER_H_ -#define _SIM_TIMER_H_ 0 +#define _SIM_TIMER_H_ 0 -#define SIM_NTIMERS 8 /* # timers */ -#define SIM_TMAX 500 /* max timer makeup */ +#define SIM_NTIMERS 8 /* # timers */ +#define SIM_TMAX 500 /* max timer makeup */ int32 sim_rtcn_init (int32 time, int32 tmr); int32 sim_rtcn_calb (int32 ticksper, int32 tmr); diff --git a/sim_tmxr.c b/sim_tmxr.c index 3eee1486..91cd3b59 100644 --- a/sim_tmxr.c +++ b/sim_tmxr.c @@ -1,6 +1,6 @@ /* sim_tmxr.c: Telnet terminal multiplexor library - Copyright (c) 2001-2004, Robert M Supnik + Copyright (c) 2001-2005, 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"), @@ -19,50 +19,53 @@ 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 + 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. - 04-Jan-04 RMS Changed TMXR ldsc to be pointer to linedesc array - Added tmxr_linemsg, circular output pointers, logging - (from Mark Pizzolato) - 29-Dec-03 RMS Added output stall support - 01-Nov-03 RMS Cleaned up attach routine - 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 + 16-Aug-05 RMS Fixed C++ declaration and cast problems + 29-Jun-05 RMS Extended tmxr_dscln to support unit array devices + Fixed bug in SET LOG/NOLOG + 04-Jan-04 RMS Changed TMXR ldsc to be pointer to linedesc array + Added tmxr_linemsg, circular output pointers, logging + (from Mark Pizzolato) + 29-Dec-03 RMS Added output stall support + 01-Nov-03 RMS Cleaned up attach routine + 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 This library includes: - tmxr_poll_conn - poll for connection - tmxr_reset_ln - reset line - tmxr_getc_ln - get character for line - tmxr_poll_rx - poll receive - tmxr_putc_ln - put character for line - tmxr_poll_tx - poll transmit - tmxr_open_master - open master connection - tmxr_close_master - close master connection - tmxr_attach - attach terminal multiplexor - tmxr_detach - detach terminal multiplexor - tmxr_ex - (null) examine - tmxr_dep - (null) deposit - tmxr_msg - send message to socket - tmxr_linemsg - send message to line - tmxr_fconns - output connection status - tmxr_fstats - output connection statistics - tmxr_dscln - disconnect line (SET routine) - tmxr_rqln - number of available characters for line - tmxr_tqln - number of buffered characters for line + tmxr_poll_conn - poll for connection + tmxr_reset_ln - reset line + tmxr_getc_ln - get character for line + tmxr_poll_rx - poll receive + tmxr_putc_ln - put character for line + tmxr_poll_tx - poll transmit + tmxr_open_master - open master connection + tmxr_close_master - close master connection + tmxr_attach - attach terminal multiplexor + tmxr_detach - detach terminal multiplexor + tmxr_ex - (null) examine + tmxr_dep - (null) deposit + tmxr_msg - send message to socket + tmxr_linemsg - send message to line + tmxr_fconns - output connection status + tmxr_fstats - output connection statistics + tmxr_dscln - disconnect line (SET routine) + tmxr_rqln - number of available characters for line + tmxr_tqln - number of buffered characters for line All routines are OS-independent. */ @@ -74,25 +77,25 @@ /* 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 */ +#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 */ +#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); int32 tmxr_send_buffered_data (TMLN *lp); @@ -102,15 +105,15 @@ 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 + *mp = pointer to terminal multiplexor descriptor Outputs: - line number activated, -1 if none + line number activated, -1 if none */ int32 tmxr_poll_conn (TMXR *mp) @@ -120,38 +123,42 @@ 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 }; + 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_linemsg (lp, "\n\r\nConnected to the "); - tmxr_linemsg (lp, sim_name); - tmxr_linemsg (lp, " simulator\r\n\n"); - tmxr_poll_tx (mp); /* flush output */ - return i; } - } /* end if newsock */ +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_linemsg (lp, "\n\r\nConnected to the "); + tmxr_linemsg (lp, sim_name); + tmxr_linemsg (lp, " simulator\r\n\n"); + tmxr_poll_tx (mp); /* flush output */ + return i; + } + } /* end if newsock */ return -1; } @@ -159,23 +166,23 @@ return -1; void tmxr_reset_ln (TMLN *lp) { -if (lp->txlog) fflush (lp->txlog); /* dump log */ -tmxr_send_buffered_data (lp); /* send buffered data */ -sim_close_sock (lp->conn, 0); /* reset conn */ -lp->conn = lp->tsta = 0; /* reset state */ +if (lp->txlog) fflush (lp->txlog); /* dump log */ +tmxr_send_buffered_data (lp); /* send buffered data */ +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 + *lp = pointer to terminal line descriptor Output: - valid + char, 0 if line + valid + char, 0 if line */ int32 tmxr_getc_ln (TMLN *lp) @@ -183,24 +190,25 @@ 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; +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 + *mp = pointer to terminal multiplexor descriptor + Outputs: none */ void tmxr_poll_rx (TMXR *mp) @@ -208,74 +216,83 @@ 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 */ +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; + 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 */ - signed 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 */ + for (; j < lp->rxbpi; ) { /* loop thru char */ + signed 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; } @@ -291,46 +308,49 @@ return (lp->rxbpi - lp->rxbpr); 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->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 + *lp = pointer to line descriptor + chr = characters Outputs: - status = ok, connection lost, or stall + status = ok, connection lost, or stall */ t_stat tmxr_putc_ln (TMLN *lp, int32 chr) { -if (lp->txlog) fputc (chr, lp->txlog); /* log if available */ -if (lp->conn == 0) return SCPE_LOST; /* no conn? lost */ -if (tmxr_tqln (lp) < (TMXR_MAXBUF - 1)) { /* room for char (+ IAC)? */ - lp->txb[lp->txbpi] = (char) chr; /* buffer char */ - lp->txbpi = lp->txbpi + 1; /* adv pointer */ - if (lp->txbpi >= TMXR_MAXBUF) lp->txbpi = 0; /* wrap? */ - if ((char) chr == TN_IAC) { /* IAC? */ - lp->txb[lp->txbpi] = (char) chr; /* IAC + IAC */ - lp->txbpi = lp->txbpi + 1; /* adv pointer */ - if (lp->txbpi >= TMXR_MAXBUF) lp->txbpi = 0; } /* wrap? */ - if (tmxr_tqln (lp) > (TMXR_MAXBUF - TMXR_GUARD))/* near full? */ - lp->xmte = 0; /* disable line */ - return SCPE_OK; } /* char sent */ -lp->xmte = 0; /* no room, dsbl line */ -return SCPE_STALL; /* char not sent */ +if (lp->txlog) fputc (chr, lp->txlog); /* log if available */ +if (lp->conn == 0) return SCPE_LOST; /* no conn? lost */ +if (tmxr_tqln (lp) < (TMXR_MAXBUF - 1)) { /* room for char (+ IAC)? */ + lp->txb[lp->txbpi] = (char) chr; /* buffer char */ + lp->txbpi = lp->txbpi + 1; /* adv pointer */ + if (lp->txbpi >= TMXR_MAXBUF) lp->txbpi = 0; /* wrap? */ + if ((char) chr == TN_IAC) { /* IAC? */ + lp->txb[lp->txbpi] = (char) chr; /* IAC + IAC */ + lp->txbpi = lp->txbpi + 1; /* adv pointer */ + if (lp->txbpi >= TMXR_MAXBUF) lp->txbpi = 0; /* wrap? */ + } + if (tmxr_tqln (lp) > (TMXR_MAXBUF - TMXR_GUARD)) /* near full? */ + lp->xmte = 0; /* disable line */ + return SCPE_OK; /* char sent */ + } +lp->xmte = 0; /* no room, dsbl line */ +return SCPE_STALL; /* char not sent */ } /* Poll for output Inputs: - *mp = pointer to terminal multiplexor descriptor + *mp = pointer to terminal multiplexor descriptor Outputs: - none + none */ void tmxr_poll_tx (TMXR *mp) @@ -338,47 +358,50 @@ void tmxr_poll_tx (TMXR *mp) int32 i, nbytes; 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 = tmxr_send_buffered_data (lp); /* buffered bytes */ - if (nbytes == 0) lp->xmte = 1; /* buf empty? enab line */ - } /* end for */ +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 = tmxr_send_buffered_data (lp); /* buffered bytes */ + if (nbytes == 0) lp->xmte = 1; /* buf empty? enab line */ + } /* end for */ return; } /* Send buffered data across network Inputs: - *lp = pointer to line descriptor + *lp = pointer to line descriptor Outputs: - returns number of bytes still buffered + returns number of bytes still buffered */ int32 tmxr_send_buffered_data (TMLN *lp) { int32 nbytes, sbytes; -nbytes = tmxr_tqln(lp); /* avail bytes */ -if (nbytes) { /* >0? write */ - if (lp->txbpr < lp->txbpi) /* no wrap? */ - sbytes = sim_write_sock (lp->conn, /* write all data */ - &(lp->txb[lp->txbpr]), nbytes); - else sbytes = sim_write_sock (lp->conn, /* write to end buf */ - &(lp->txb[lp->txbpr]), TMXR_MAXBUF - lp->txbpr); - if (sbytes != SOCKET_ERROR) { /* ok? */ - lp->txbpr = (lp->txbpr + sbytes); /* update remove ptr */ - if (lp->txbpr >= TMXR_MAXBUF) lp->txbpr = 0;/* wrap? */ - lp->txcnt = lp->txcnt + sbytes; /* update counts */ - nbytes = nbytes - sbytes; } - if (nbytes && (lp->txbpr == 0)) { /* more data and wrap? */ - sbytes = sim_write_sock (lp->conn, lp->txb, nbytes); - if (sbytes != SOCKET_ERROR) { /* ok */ - lp->txbpr = (lp->txbpr + sbytes); /* update remove ptr */ - if (lp->txbpr >= TMXR_MAXBUF) lp->txbpr = 0;/* wrap? */ - lp->txcnt = lp->txcnt + sbytes; /* update counts */ - nbytes = nbytes - sbytes; } } - } /* end if nbytes */ +nbytes = tmxr_tqln(lp); /* avail bytes */ +if (nbytes) { /* >0? write */ + if (lp->txbpr < lp->txbpi) /* no wrap? */ + sbytes = sim_write_sock (lp->conn, /* write all data */ + &(lp->txb[lp->txbpr]), nbytes); + else sbytes = sim_write_sock (lp->conn, /* write to end buf */ + &(lp->txb[lp->txbpr]), TMXR_MAXBUF - lp->txbpr); + if (sbytes != SOCKET_ERROR) { /* ok? */ + lp->txbpr = (lp->txbpr + sbytes); /* update remove ptr */ + if (lp->txbpr >= TMXR_MAXBUF) lp->txbpr = 0; /* wrap? */ + lp->txcnt = lp->txcnt + sbytes; /* update counts */ + nbytes = nbytes - sbytes; + } + if (nbytes && (lp->txbpr == 0)) { /* more data and wrap? */ + sbytes = sim_write_sock (lp->conn, lp->txb, nbytes); + if (sbytes != SOCKET_ERROR) { /* ok */ + lp->txbpr = (lp->txbpr + sbytes); /* update remove ptr */ + if (lp->txbpr >= TMXR_MAXBUF) lp->txbpr = 0;/* wrap? */ + lp->txcnt = lp->txcnt + sbytes; /* update counts */ + nbytes = nbytes - sbytes; + } + } + } /* end if nbytes */ return nbytes; } @@ -388,7 +411,7 @@ int32 tmxr_tqln (TMLN *lp) { return (lp->txbpi - lp->txbpr + ((lp->txbpi < lp->txbpr)? TMXR_MAXBUF: 0)); } - + /* Open master socket */ t_stat tmxr_open_master (TMXR *mp, char *cptr) @@ -398,23 +421,24 @@ SOCKET sock; TMLN *lp; t_stat r; -port = (int32) get_uint (cptr, 10, 65535, &r); /* get port */ +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 */ +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; } + "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; } @@ -425,15 +449,16 @@ t_stat tmxr_attach (TMXR *mp, UNIT *uptr, char *cptr) char* tptr; t_stat 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 */ +tptr = (char *) 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; } @@ -444,15 +469,16 @@ 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_linemsg (lp, "\r\nDisconnected from the "); - tmxr_linemsg (lp, sim_name); - tmxr_linemsg (lp, " simulator\r\n\n"); - tmxr_reset_ln (lp); } /* end if conn */ - } /* end for */ -sim_close_sock (mp->master, 1); /* close master socket */ +for (i = 0; i < mp->lines; i++) { /* loop thru conn */ + lp = mp->ldsc + i; + if (lp->conn) { + tmxr_linemsg (lp, "\r\nDisconnected from the "); + tmxr_linemsg (lp, sim_name); + tmxr_linemsg (lp, " 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; } @@ -461,11 +487,11 @@ return SCPE_OK; t_stat tmxr_detach (TMXR *mp, UNIT *uptr) { -if (!(uptr->flags & UNIT_ATT)) return SCPE_OK; /* attached? */ -tmxr_close_master (mp); /* close master socket */ -free (uptr->filename); /* free port string */ +if (!(uptr->flags & UNIT_ATT)) 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 */ +uptr->flags = uptr->flags & ~UNIT_ATT; /* not attached */ return SCPE_OK; } @@ -494,7 +520,7 @@ void tmxr_linemsg (TMLN *lp, char *msg) int32 len; for (len = strlen (msg); len > 0; --len) - tmxr_putc_ln (lp, *msg++); + tmxr_putc_ln (lp, *msg++); return; } @@ -504,19 +530,20 @@ 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; + 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); } + 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"); if (lp->txlog) fprintf (st, "Logging to %s\n", lp->txlogname); return; @@ -531,12 +558,13 @@ 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); } + 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; } @@ -550,15 +578,21 @@ 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 (mp == NULL) return SCPE_IERR; +if (val) { /* = n form */ + if (cptr == NULL) return SCPE_ARG; + ln = (int32) get_uint (cptr, 10, mp->lines - 1, &r); + if (r != SCPE_OK) return SCPE_ARG; + lp = mp->ldsc + ln; + } +else { + lp = tmxr_find_ldsc (uptr, 0, mp); + if (lp == NULL) return SCPE_IERR; + } if (lp->conn) { - tmxr_linemsg (lp, "\r\nOperator disconnected line\r\n\n"); - tmxr_reset_ln (lp); } + tmxr_linemsg (lp, "\r\nOperator disconnected line\r\n\n"); + tmxr_reset_ln (lp); + } return SCPE_OK; } @@ -569,17 +603,18 @@ t_stat tmxr_set_log (UNIT *uptr, int32 val, char *cptr, void *desc) TMXR *mp = (TMXR *) desc; TMLN *lp; -if (cptr == NULL) return SCPE_2FARG; /* no file name? */ -lp = tmxr_find_ldsc (uptr, val, mp); /* find line desc */ +if (cptr == NULL) return SCPE_2FARG; /* no file name? */ +lp = tmxr_find_ldsc (uptr, val, mp); /* find line desc */ if (lp == NULL) return SCPE_IERR; -if (lp->txlog) tmxr_set_nolog (NULL, val, NULL, desc); /* close existing log */ -lp->txlogname = calloc (CBUFSIZE, sizeof (char)); /* alloc namebuf */ -if (lp->txlogname == NULL) return SCPE_MEM; /* can't? */ -strncpy (lp->txlogname, cptr, CBUFSIZE); /* save file name */ -lp->txlog = fopen (cptr, "ab"); /* open log */ -if (lp->txlog == NULL) { /* error? */ - free (lp->txlogname); /* free buffer */ - return SCPE_OPENERR; } +if (lp->txlog) tmxr_set_nolog (NULL, val, NULL, desc); /* close existing log */ +lp->txlogname = (char *) calloc (CBUFSIZE, sizeof (char)); /* alloc namebuf */ +if (lp->txlogname == NULL) return SCPE_MEM; /* can't? */ +strncpy (lp->txlogname, cptr, CBUFSIZE); /* save file name */ +lp->txlog = fopen (cptr, "ab"); /* open log */ +if (lp->txlog == NULL) { /* error? */ + free (lp->txlogname); /* free buffer */ + return SCPE_OPENERR; + } return SCPE_OK; } @@ -590,14 +625,15 @@ t_stat tmxr_set_nolog (UNIT *uptr, int32 val, char *cptr, void *desc) TMXR *mp = (TMXR *) desc; TMLN *lp; -if (cptr) return SCPE_2MARG; /* no arguments */ -lp = tmxr_find_ldsc (uptr, val, mp); /* find line desc */ +if (cptr) return SCPE_2MARG; /* no arguments */ +lp = tmxr_find_ldsc (uptr, val, mp); /* find line desc */ if (lp == NULL) return SCPE_IERR; -if (lp->txlog) { /* logging? */ - fclose (lp->txlog); /* close log */ - free (lp->txlogname); /* free namebuf */ - lp->txlog = NULL; - lp->txlogname = NULL; } +if (lp->txlog) { /* logging? */ + fclose (lp->txlog); /* close log */ + free (lp->txlogname); /* free namebuf */ + lp->txlog = NULL; + lp->txlogname = NULL; + } return SCPE_OK; } @@ -608,7 +644,7 @@ t_stat tmxr_show_log (FILE *st, UNIT *uptr, int32 val, void *desc) TMXR *mp = (TMXR *) desc; TMLN *lp; -lp = tmxr_find_ldsc (uptr, val, mp); /* find line desc */ +lp = tmxr_find_ldsc (uptr, val, mp); /* find line desc */ if (lp == NULL) return SCPE_IERR; if (lp->txlog) fprintf (st, "logging to %s", lp->txlogname); else fprintf (st, "no logging"); @@ -619,10 +655,11 @@ return SCPE_OK; TMLN *tmxr_find_ldsc (UNIT *uptr, int32 val, TMXR *mp) { -if (uptr) { /* called from SET? */ - DEVICE *dptr = find_dev_from_unit (uptr); /* find device */ - if (dptr == NULL) return NULL; /* what?? */ - val = uptr - dptr->units; } /* implicit line # */ -if ((val < 0) || (val >= mp->lines)) return NULL; /* invalid line? */ -return mp->ldsc + val; /* line descriptor */ +if (uptr) { /* called from SET? */ + DEVICE *dptr = find_dev_from_unit (uptr); /* find device */ + if (dptr == NULL) return NULL; /* what?? */ + val = (int32) (uptr - dptr->units); /* implicit line # */ + } +if ((val < 0) || (val >= mp->lines)) return NULL; /* invalid line? */ +return mp->ldsc + val; /* line descriptor */ } diff --git a/sim_tmxr.h b/sim_tmxr.h index ac692afd..c9a299e0 100644 --- a/sim_tmxr.h +++ b/sim_tmxr.h @@ -1,6 +1,6 @@ /* sim_tmxr.h: terminal multiplexor definitions - Copyright (c) 2001-2004, Robert M Supnik + Copyright (c) 2001-2005, 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"), @@ -19,60 +19,60 @@ 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 + 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. - 04-Jan-04 RMS Changed TMXR ldsc to be pointer to linedesc array - Added tmxr_linemsg, logging (from Mark Pizzolato) - 29-Dec-03 RMS Added output stall support, increased buffer size - 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 + 04-Jan-04 RMS Changed TMXR ldsc to be pointer to linedesc array + Added tmxr_linemsg, logging (from Mark Pizzolato) + 29-Dec-03 RMS Added output stall support, increased buffer size + 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 _SIM_TMXR_H_ 0 -#define TMXR_V_VALID 15 -#define TMXR_VALID (1 << TMXR_V_VALID) -#define TMXR_MAXBUF 256 /* buffer size */ -#define TMXR_GUARD 12 /* buffer guard */ +#define TMXR_V_VALID 15 +#define TMXR_VALID (1 << TMXR_V_VALID) +#define TMXR_MAXBUF 256 /* buffer size */ +#define TMXR_GUARD 12 /* buffer guard */ 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 */ - FILE *txlog; /* xmt log file */ - char *txlogname; /* xmt log file name */ - char rxb[TMXR_MAXBUF]; /* rcv buffer */ - char rbr[TMXR_MAXBUF]; /* rcv break */ - char txb[TMXR_MAXBUF]; /* xmt buffer */ - }; + 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 */ + FILE *txlog; /* xmt log file */ + char *txlogname; /* xmt log file name */ + 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; /* line descriptors */ - }; + int32 lines; /* # lines */ + int32 port; /* listening port */ + SOCKET master; /* master socket */ + TMLN *ldsc; /* line descriptors */ + }; typedef struct tmxr TMXR; diff --git a/simh_doc.txt b/simh_doc.txt index 25b0421d..0f158f30 100644 --- a/simh_doc.txt +++ b/simh_doc.txt @@ -1,7 +1,7 @@ To: Users From: Bob Supnik Subj: Simulator Usage, V3.4 -Date: 01-May-2005 +Date: 20-Jul-2005 COPYRIGHT NOTICE @@ -27,8 +27,8 @@ The following copyright notice applies to both the SIMH source and binary: 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 + 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; @@ -885,6 +885,11 @@ 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. +SIMH can read Pierce-format seven-track magtape images. Pierce format +uses only 6 data bits, and one parity bit, in each byte. The high +order bit indicates start of record. End of file is indicated by a +record of one (occasionally two) bytes consisting of code 017 (octal). + 4. Line Printers Line printer output is represented by an ASCII file of lines separated @@ -981,23 +986,23 @@ drum - - - - h DECtape - - - - - mag tape - - d y h - system LGP-30 1130 + system LGP-30 1130 7094 device -CPU h y -FPU - - -CIS - - -console h y -paper tape h - -card reader - y -line printer - y -clock - - -extra terminal - - -hard disk - y -fixed disk - - -floppy disk - - -drum - - -DECtape - - -mag tape - - +CPU h y d +FPU - - d +CIS - - - +console h y - +paper tape h - - +card reader - y h +line printer - y h +clock - - n +extra terminal - - n +hard disk - y d +fixed disk - - d +floppy disk - - - +drum - - d +DECtape - - - +mag tape - - h legend: y = runs operating system or sample program d = runs diagnostics @@ -1012,6 +1017,7 @@ in file sim_rev.c. Rev 3.4, May, 05 Revised memory interaction model + Added IBM 7094 Rev 3.3, Nov, 04 Added PDP-11/VAX DHQ11 support diff --git a/simh_faq.txt b/simh_faq.txt index 0ad711ce..36867f59 100644 --- a/simh_faq.txt +++ b/simh_faq.txt @@ -1,4 +1,4 @@ -SIMH FAQ, 31-Mar-2004 +SIMH FAQ, 07-Sep-2005 1 General @@ -21,12 +21,12 @@ SIMH FAQ, 31-Mar-2004 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.5 How do I transcribe a real CD for use with SIMH? [Updated] 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? +2.10 My Windows host can't communicate with the PDP-11 or VAX over Ethernet; why? [Updated] 2.11 How can I use my wireless Ethernet card with SIMH? -------------------------------------------------------------------------------- @@ -142,7 +142,7 @@ SIMH simulates the following computer systems: 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 + IBM Corporation 1130, 1401, 1620, System 3, 7094 GRI Corporation GRI-909 Honeywell Corporation H316/516 Hewlett Packard Corporation HP2116, HP2100, HP21MX @@ -211,7 +211,7 @@ ka655x.bin from the source kit. 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 + http://www.winpcap.org This creates a network packet driver in Windows for SIMH to attach to. @@ -254,6 +254,7 @@ On a VAX use: $ MMx On a Alpha use: + $ MMx/MACRO=("__ALPHA__=1") !Without ethernet support $ MMx/MACRO=("__ALPHA__=1","__PCAP__=1") !With ethernet support @@ -285,17 +286,26 @@ emulators. Ethernet support is only available on Alpha VMS 7.3-1 and above. 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. + + You may also need to limit the read speed. Some burnt CD-Rs do not read + correctly at the highest rate of speed, depending on the accuracy of the + burner; pressed CD-ROMs should not have this problem. - 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. + 1) Roxio + A) 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. + B) Easy Media Creator 7.x + Go to Creator Classic + Select Other Tasks | Disc and Device Utility + Drill down on the device until you find the data track, then select it + 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 -------------------------------------------------------------------------------- @@ -377,6 +387,11 @@ 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. +Attaching the ethernet device to a TAP-Win32 pseudo-controller can also solve +this problem, since you would normally bridge the pseudo-controller to the main +ethernet controller; the simulated system and the host will communicate over +the bridge. TAP-Win32 is a component of OpenVPN software: http://openvpn.net. + -------------------------------------------------------------------------------- 2.11 How can I use my wireless Ethernet card with SIMH? @@ -482,7 +497,7 @@ 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 +important bug fixes, has accumulated. This has averaged every 8-16 weeks. The major version number only changes when there is a major restructuring of SIMH's internal structures. The minor version number is changed when the format of the save/restore file must be updated. @@ -495,7 +510,7 @@ is changed when the format of the save/restore file must be updated. 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/. +found on http://www.openvmshobbyist.com. -------------------------------------------------------------------------------- @@ -580,7 +595,7 @@ 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> att ptr ka655x.bin sim> ie ptr 4 4: 2 1 sim> det ptr @@ -601,7 +616,7 @@ 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> load -r vax\ka655x.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 ; " @@ -642,7 +657,7 @@ Ethernet Adapter 0 (774440) - 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. + limited 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. diff --git a/simh_swre.txt b/simh_swre.txt index 172766d5..a59257cf 100644 --- a/simh_swre.txt +++ b/simh_swre.txt @@ -10,8 +10,8 @@ software. The following copyright notice applies to both the SIMH source and binary: - Original code published in 1993-2004, written by Robert M Supnik - Copyright (c) 1993-2004, Robert M Supnik + Original code published in 1993-2005, written by Robert M Supnik + Copyright (c) 1993-2005, 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"), @@ -30,8 +30,8 @@ The following copyright notice applies to both the SIMH source and binary: 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 + 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